
鼠标移动波纹动画

鼠标移动波纹动画,特别炫酷~
鼠标移动波纹动画,特别炫酷~
const E = {
friction: 0.5,
trails: 20,
size: 50,
dampening: 0.25,
tension: 0.98,
};
class Wave {
phase = 0;
offset = 0;
frequency = 0.001;
amplitude = 1;
constructor(e) {
this.phase = e.phase || 0;
this.offset = e.offset || 0;
this.frequency = e.frequency || 0.001;
this.amplitude = e.amplitude || 1;
}
update() {
this.phase += this.frequency;
return this.offset + Math.sin(this.phase) * this.amplitude;
}
}
class Node {
x = 0;
y = 0;
vy = 0;
vx = 0;
}
class Line {
spring = 0.1;
friction = 0.01;
nodes = [];
constructor(e, pos) {
this.spring = e.spring + 0.1 * Math.random() - 0.05;
this.friction = E.friction + 0.01 * Math.random() - 0.005;
this.nodes = [];
this.pos = pos;
for (let i = 0; i < E.size; i++) {
const t = new Node();
t.x = this.pos.x;
t.y = this.pos.y;
this.nodes.push(t);
}
}
update() {
let { spring } = this;
let node = this.nodes[0];
node.vx += (this.pos.x - node.x) * spring;
node.vy += (this.pos.y - node.y) * spring;
let prevNode;
for (let i = 0; i < this.nodes.length; i++) {
node = this.nodes[i];
if (i > 0) {
prevNode = this.nodes[i - 1];
node.vx += (prevNode.x - node.x) * spring;
node.vy += (prevNode.y - node.y) * spring;
node.vx += prevNode.vx * E.dampening;
node.vy += prevNode.vy * E.dampening;
}
node.vx *= this.friction;
node.vy *= this.friction;
node.x += node.vx;
node.y += node.vy;
spring *= E.tension;
}
}
draw(ctx) {
let currNode;
let nextNode;
let { x } = this.nodes[0];
let { y } = this.nodes[0];
ctx.beginPath();
ctx.moveTo(x, y);
let i;
for (i = 1; i < this.nodes.length - 2; i++) {
currNode = this.nodes[i];
nextNode = this.nodes[i + 1];
x = 0.5 * (currNode.x + nextNode.x);
y = 0.5 * (currNode.y + nextNode.y);
ctx.quadraticCurveTo(currNode.x, currNode.y, x, y);
}
currNode = this.nodes[i];
nextNode = this.nodes[i + 1];
ctx.quadraticCurveTo(currNode.x, currNode.y, nextNode.x, nextNode.y);
ctx.stroke();
ctx.closePath();
}
}
export const renderCanvas = () => {
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let lines = [];
const pos = { x: 0, y: 0 };
const wave = new Wave({
phase: Math.random() * 2 * Math.PI,
amplitude: 85,
frequency: 0.0015,
offset: 285,
});
let running = true;
function resizeCanvas() {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
}
resizeCanvas();
function animate() {
if (running) {
ctx.globalCompositeOperation = "source-over";
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.globalCompositeOperation = "lighter";
ctx.strokeStyle = `hsla(${Math.round(wave.update())},90%,50%,0.25)`;
ctx.lineWidth = 1;
for (let i = 0; i < E.trails; i++) {
const line = lines[i];
line.update();
line.draw(ctx);
}
window.requestAnimationFrame(animate);
}
}
function bindMouseMove(event) {
function drawLine() {
lines = [];
for (let i = 0; i < E.trails; i++) {
lines.push(new Line({ spring: 0.45 + (i / E.trails) * 0.025 }, pos));
}
}
function move(e) {
e.preventDefault();
if (e.touches) {
pos.x = e.touches[0].pageX;
pos.y = e.touches[0].pageY;
} else {
pos.x = e.clientX;
pos.y = e.clientY;
}
}
function start(e) {
if (e.touches.length === 1) {
pos.x = e.touches[0].pageX;
pos.y = e.touches[0].pageY;
}
}
document.removeEventListener("mousemove", bindMouseMove);
document.removeEventListener("touchstart", bindMouseMove);
document.addEventListener("mousemove", move);
document.addEventListener("touchmove", move);
document.addEventListener("touchstart", start);
move(event);
drawLine();
animate();
}
document.addEventListener("mousemove", bindMouseMove);
document.addEventListener("touchstart", bindMouseMove);
document.body.addEventListener("orientationchange", resizeCanvas);
window.addEventListener("resize", resizeCanvas);
window.addEventListener("focus", () => {
if (!running) {
running = true;
animate();
}
});
window.addEventListener("blur", () => {
running = true;
});
};
// 创建canvas元素
<canvas id="canvas" class="canvas"></canvas>
// 渲染粒子效果
renderCanvas();
您需要登录后才能访问此功能
请点击下方按钮登录您的账号,以便访问更多功能。
分享创造,拥抱快乐
本文由 ssbrother 创作并发布于 绝对の领域KrzACG