(function() {
'use strict';
const config = {
petalCount: 30, // 花瓣数量
colors: ['#ffb7c5', '#39b4cf', '#e87339', '#f4a7b9', '#8b1cb3'],
windSpeed: 0.5,
gravity: 0.3,
mouseForce: 0.8
};
let canvas, ctx;
let petals = [];
let mouse = { x: -1000, y: -1000, vx: 0, vy: 0 };
let lastMouse = { x: -1000, y: -1000 };
let animationId;
class Petal {
constructor() {
this.reset(true);
}
reset(randomY = false) {
this.x = Math.random() * canvas.width;
this.y = randomY ? Math.random() * canvas.height : -20;
this.size = Math.random() * 8 + 5;
this.speedY = Math.random() * 1 + 0.5;
this.speedX = Math.random() * 2 - 1;
this.rotation = Math.random() * 360;
this.rotationSpeed = (Math.random() - 0.5) * 2;
this.opacity = Math.random() * 0.4 + 0.3;
this.color = config.colors[Math.floor(Math.random() * config.colors.length)];
this.swayAmount = Math.random() * 2 + 1;
this.swaySpeed = Math.random() * 0.02 + 0.01;
this.time = Math.random() * Math.PI * 2;
}
update() {
this.time += this.swaySpeed;
// 基础运动
this.y += this.speedY + config.gravity;
this.x += Math.sin(this.time) * this.swayAmount + config.windSpeed;
this.rotation += this.rotationSpeed;
// 鼠标交互
const dx = this.x - mouse.x;
const dy = this.y - mouse.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
const force = (150 - distance) / 150;
this.x += mouse.vx * force * config.mouseForce;
this.y += mouse.vy * force * config.mouseForce;
this.rotationSpeed += mouse.vx * 0.01;
}
// 边界检查
if (this.y > canvas.height + 20 || this.x > canvas.width + 20 || this.x < -20) {
this.reset();
}
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.rotation * Math.PI / 180);
ctx.globalAlpha = this.opacity;
ctx.fillStyle = this.color;
// 绘制花瓣形状
ctx.beginPath();
ctx.moveTo(0, -this.size);
ctx.bezierCurveTo(
this.size * 0.5, -this.size * 0.5,
this.size, 0,
0, this.size
);
ctx.bezierCurveTo(
-this.size, 0,
-this.size * 0.5, -this.size * 0.5,
0, -this.size
);
ctx.fill();
ctx.restore();
}
}
function init() {
canvas = document.createElement('canvas');
canvas.id = 'cursor-effect-canvas';
canvas.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9999;';
document.body.appendChild(canvas);
ctx = canvas.getContext('2d');
resize();
window.addEventListener('resize', resize);
for (let i = 0; i < config.petalCount; i++) {
petals.push(new Petal());
}
document.addEventListener('mousemove', (e) => {
mouse.vx = e.clientX - lastMouse.x;
mouse.vy = e.clientY - lastMouse.y;
lastMouse.x = mouse.x = e.clientX;
lastMouse.y = mouse.y = e.clientY;
});
animate();
}
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
petals.forEach(petal => {
petal.update();
petal.draw();
});
animationId = requestAnimationFrame(animate);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
阅读
30
|
点赞
2
评论已关闭