文章图标

鼠标移动波纹动画

简介图标

鼠标移动波纹动画,特别炫酷~

广告图标

神奇小广告

ssbrother/pixpin_2024-10-30_11-46-41-20241030063230.gif

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

参与讨论
精彩评论正在加载中...
sign-inGo to tasks