1
0
forked from C9S/mono-landing
This commit is contained in:
Alex Ant
2026-03-16 12:22:49 +05:00
parent ca55922c7a
commit ffb1e41f36
2 changed files with 21 additions and 177 deletions
-169
View File
@@ -1,169 +0,0 @@
// heroAnimator.js
// dependency: anime.js
export class HeroAnimator {
constructor(el, type = 'hex', options = {}) {
this.container = typeof el === 'string' ? document.querySelector(el) : el
this.type = type
this.options = options
this.canvas = document.createElement('canvas')
this.ctx = this.canvas.getContext('2d')
this.container.appendChild(this.canvas)
this.resize()
window.addEventListener('resize', () => this.resize())
if (type === 'hex') this.initHex()
if (type === 'waves') this.initWaves()
}
resize() {
this.width = this.container.offsetWidth
this.height = this.container.offsetHeight
this.canvas.width = this.width
this.canvas.height = this.height
}
// =========================
// HEX GRID
// =========================
initHex() {
const size = this.options.size || 40
const rows = Math.ceil(this.height / size) + 2
const cols = Math.ceil(this.width / size) + 2
this.hexPoints = []
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
const offset = y % 2 ? size / 2 : 0
this.hexPoints.push({
x: x * size + offset,
y: y * size * 0.86,
scale: 1
})
}
}
anime({
targets: this.hexPoints,
scale: [
{ value: 1.006 },
{ value: 0.994 },
{ value: 1 }
],
easing: "easeInOutSine",
duration: 12000,
delay: anime.stagger(80),
loop: true,
update: () => this.drawHex()
})
}
drawHex() {
const ctx = this.ctx
ctx.clearRect(0, 0, this.width, this.height)
const r = this.options.size || 40
this.hexPoints.forEach(p => {
const radius = r * 0.5 * p.scale
ctx.beginPath()
for (let i = 0; i < 6; i++) {
const angle = Math.PI / 3 * i
const x = p.x + radius * Math.cos(angle)
const y = p.y + radius * Math.sin(angle)
if (i === 0) ctx.moveTo(x, y)
else ctx.lineTo(x, y)
}
ctx.closePath()
ctx.strokeStyle = this.options.stroke || "rgba(255,252,240,0.06)"
ctx.stroke()
})
}
// =========================
// WAVE GRID
// =========================
initWaves() {
this.t = 0
const animate = () => {
this.t += 0.02
this.drawWaves()
requestAnimationFrame(animate)
}
animate()
}
drawWaves() {
const ctx = this.ctx
ctx.clearRect(0,0,this.width,this.height)
const base = this.height / 2
const step = this.width / 120
ctx.lineWidth = 1.5
ctx.strokeStyle = "rgba(255,255,255,0.2)"
const draw = (amp, freq, phase) => {
ctx.beginPath()
for (let x = 0; x <= this.width; x += step) {
const y =
base +
Math.sin(x * freq + this.t + phase) * amp
if (x === 0) ctx.moveTo(x,y)
else ctx.lineTo(x,y)
}
ctx.stroke()
}
// 5 верхних волн
for (let i = 0; i < 5; i++) {
draw(20 + i * 6, 0.01 + i * 0.002, i)
}
// 3 нижних
for (let i = 0; i < 3; i++) {
draw(-30 - i * 8, 0.015 + i * 0.002, i)
}
}
}
+21 -8
View File
@@ -67,16 +67,29 @@ function initHeroHex() {
function startAnim() {
window._hexStart = performance.now();
var startTime = window._hexStart;
var lastDraw = 0;
var targetInterval = 1000 / 30;
var rafId;
function tick() {
var t = (performance.now() - startTime) / 1000;
hexPoints.forEach(function (p) {
var cycle = (t / 4.5 + p.phase) % 1;
p.scale = 1 + 0.25 * Math.sin(cycle * Math.PI);
});
drawHex(t);
requestAnimationFrame(tick);
var now = performance.now();
if (now - lastDraw >= targetInterval) {
lastDraw = now;
var t = (now - startTime) / 1000;
hexPoints.forEach(function (p) {
var cycle = (t / 4.5 + p.phase) % 1;
p.scale = 1 + 0.25 * Math.sin(cycle * Math.PI);
});
drawHex(t);
}
rafId = requestAnimationFrame(tick);
}
tick();
var hero = document.getElementById('hero');
var io = hero && typeof IntersectionObserver !== 'undefined' ? new IntersectionObserver(function (e) {
if (e[0].isIntersecting) { lastDraw = 0; rafId = requestAnimationFrame(tick); }
else if (rafId) { cancelAnimationFrame(rafId); rafId = null; }
}, { threshold: 0 }) : null;
if (io && hero) io.observe(hero);
if (!io || !hero) tick();
}
function onResize() {