如何在图像画布上创建淡入淡出的光标轨迹



>我在图像画布上创建了一个光标轨迹,其中图像画布位于背景中,光标轨迹位于图像画布顶部的第二个画布上。我目前面临的问题是,我无法创建一条逐渐消失的痕迹。

我已经看到了有关如何使用 fillStyle 使其以纯背景淡入淡出的提示,但我不知道如何使淡入淡出的光标轨迹以图像作为背景。

<!DOCTYPE html>
<html>
  <head>
    <style>
      .stack {
        position: relative;
      }
      .stack canvas {
        position: absolute;
        left: 0;
        top: 0;
      }
      .stack,
      #main_canvas {
        background-size: contain;
        width: 100%;
        margin: auto;
      }
    </style>
  </head>
  <body>
    <div class="stack">
      <canvas id="main_canvas"> main canvas</canvas>
    </div>
    <script>
      var SCREEN_WIDTH = window.innerWidth;
      var SCREEN_HEIGHT = window.innerHeight;
      var RADIUS = 70;
      var RADIUS_SCALE = 1;
      var RADIUS_SCALE_MIN = 1;
      var RADIUS_SCALE_MAX = 1.5;
      var QUANTITY = 25;
      var canvas;
      var canvas_bg;
      var context;
      var context_bg;
      var particles;
      var slider_image;
      var mouseX = SCREEN_WIDTH * 0.5;
      var mouseY = SCREEN_HEIGHT * 0.5;
      var mouseIsDown = false;
      var ind = 0;
      function init() {
        canvas = document.getElementById("main_canvas");
        canvas_bg = document.createElement("canvas"); //<canvas> predefined
        canvas.setAttribute("alt", "countless stars");
        if (canvas && canvas.getContext) {
          windowResizeHandler();
          //background canvas
          create_sliders();
          //main canvas for creating  mouse trails
          context = canvas.getContext("2d");
          // Register event listeners
          window.addEventListener("mousemove", documentMouseMoveHandler, false);
          window.addEventListener("mousedown", documentMouseDownHandler, false);
          window.addEventListener("mouseup", documentMouseUpHandler, false);
          document.addEventListener(
            "touchstart",
            documentTouchStartHandler,
            false
          );
          document.addEventListener(
            "touchmove",
            documentTouchMoveHandler,
            false
          );
          window.addEventListener("resize", windowResizeHandler, false);
          createParticles();
          setInterval(loop, 1000 / 60);
        }
      }
      function create_sliders() {
        slider_image = new Image();
        slider_image.src =
          "https://images.pexels.com/photos/956999/milky-way-starry-sky-night-sky-star-956999.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940";
        canvas_bg.width = canvas.width;
        canvas_bg.height = canvas.height;
        // insert into DOM on top:
        canvas.parentNode.insertBefore(canvas_bg, canvas);
        context_bg = canvas_bg.getContext("2d");
        context_bg.drawImage(slider_image, 0, 0, canvas.width, canvas.height);
      }
      function createParticles() {
        particles = [];
        for (var i = 0; i < QUANTITY; i++) {
          var particle = {
            size: 1,
            position: { x: mouseX, y: mouseY },
            offset: { x: 0, y: 0 },
            shift: { x: mouseX, y: mouseY },
            speed: 0.01 + Math.random() * 0.04,
            targetSize: 1,
            fillColor:
              "#" + ((Math.random() * 0x404040 + 0xaaaaaa) | 0).toString(16),
            orbit: RADIUS * 0.5 + RADIUS * 0.5 * Math.random()
          };
          particles.push(particle);
        }
      }
      function documentMouseMoveHandler(event) {
        mouseX = event.clientX - (window.innerWidth - SCREEN_WIDTH) * 0.5;
        mouseY = event.clientY - (window.innerHeight - SCREEN_HEIGHT) * 0.5;
      }
      function documentMouseDownHandler(event) {
        mouseIsDown = true;
      }
      function documentMouseUpHandler(event) {
        mouseIsDown = false;
      }
      function documentTouchStartHandler(event) {
        if (event.touches.length == 1) {
          event.preventDefault();
          mouseX =
            event.touches[0].pageX - (window.innerWidth - SCREEN_WIDTH) * 0.5;
          mouseY =
            event.touches[0].pageY - (window.innerHeight - SCREEN_HEIGHT) * 0.5;
        }
      }
      function documentTouchMoveHandler(event) {
        if (event.touches.length == 1) {
          event.preventDefault();
          mouseX =
            event.touches[0].pageX - (window.innerWidth - SCREEN_WIDTH) * 0.5;
          mouseY =
            event.touches[0].pageY - (window.innerHeight - SCREEN_HEIGHT) * 0.5;
        }
      }
      function windowResizeHandler() {
        SCREEN_WIDTH = window.innerWidth;
        SCREEN_HEIGHT = window.innerHeight;
        canvas.width = SCREEN_WIDTH;
        canvas.height = SCREEN_HEIGHT;
      }
      function loop() {
        if (mouseIsDown) {
          RADIUS_SCALE += (RADIUS_SCALE_MAX - RADIUS_SCALE) * 0.02;
        } else {
          RADIUS_SCALE -= (RADIUS_SCALE - RADIUS_SCALE_MIN) * 0.02;
        }
        RADIUS_SCALE = Math.min(RADIUS_SCALE, RADIUS_SCALE_MAX);
        // context.fillStyle = 'rgba(0,0,0,0.05)';
        context.fillStyle = "rgba(0, 0, 0, 0)";
        context.fillRect(0, 0, context.canvas.width, context.canvas.height);
        for (i = 0, len = particles.length; i < len; i++) {
          var particle = particles[i];
          var lp = { x: particle.position.x, y: particle.position.y };
          // Rotation
          particle.offset.x += particle.speed;
          particle.offset.y += particle.speed;
          // Follow mouse with some lag
          particle.shift.x += (mouseX - particle.shift.x) * particle.speed;
          particle.shift.y += (mouseY - particle.shift.y) * particle.speed;
          // Apply position
          particle.position.x =
            particle.shift.x +
            Math.cos(i + particle.offset.x) * (particle.orbit * RADIUS_SCALE);
          particle.position.y =
            particle.shift.y +
            Math.sin(i + particle.offset.y) * (particle.orbit * RADIUS_SCALE);
          // Limit to screen bounds
          particle.position.x = Math.max(
            Math.min(particle.position.x, SCREEN_WIDTH),
            0
          );
          particle.position.y = Math.max(
            Math.min(particle.position.y, SCREEN_HEIGHT),
            0
          );
          particle.size += (particle.targetSize - particle.size) * 0.05;
          if (Math.round(particle.size) == Math.round(particle.targetSize)) {
            particle.targetSize = 1 + Math.random() * 7;
          }
          if (particle.position) context.beginPath();
          context.fillStyle = particle.fillColor;
          context.strokeStyle = particle.fillColor;
          context.lineWidth = particle.size;
          context.moveTo(lp.x, lp.y);
          context.lineTo(particle.position.x, particle.position.y);
          context.stroke();
          context.arc(
            particle.position.x,
            particle.position.y,
            particle.size / 2,
            0,
            Math.PI * 2,
            true
          );
          context.fill();
        }
      }
      window.onload = init;
    </script>
  </body>
</html>

目前,较旧的小径不会消失,它正在创造更像我不想要的油漆效果。

出粒子的一种方法是将(当前透明(drawRect调用替换为drawImage,该在将粒子添加到当前帧之前,在每个帧上绘制背景图像的半透明副本:

  In your loop() function:
  // Instead of this:
  // context.fillStyle = "rgba(0, 0, 0, 0)";
  // context.fillRect(0, 0, context.canvas.width, context.canvas.height);
  // Do this:
  context.save();
  context.globalAlpha = 0.1;
  context.drawImage(slider_image, 0, 0, canvas.width, canvas.height);
  context.restore();
  for (i = 0, len = particles.length; i < len; i++) {
    ...

最新更新