search

Home  >  Q&A  >  body text

ctx alternate. Use strokeStyle when using requestAnimationFrame()

<p>I'm trying to draw simple random motion as the background canvas for my landing page and I'm having trouble getting the lines to have a unique color. <br /><br /> I also tried changing it after the movie with no success (just looks like mixed colors). </p><p><br /></p> <p><br /></p> <pre class="brush:js;toolbar:false;">const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); //ctx.canvas.width = window.innerWidth; //ctx.canvas.height = window.innerHeight*4; const numSteps = ctx.canvas.width / 2 10; const stepSize = 10; const startX = 0; const startY = canvas.height / 2; const timeInterval = 15; var Point = function(color_inp){ this.x = startX; this.y = startY; this.color = color_inp; } const colors = [ '#FF1493', // Pink '#FF00FF', // Magenta '#800080', // Purple '#4B0082', // Indigo '#0000FF', // Blue '#00FFFF', // Cyan '#00FF00', // Green '#FFFF00', // Yellow '#FF7F00', // Orange '#8B4513' // Saddle Brown ]; function drawRandomWalk(stPoint, steps) { ctx.globalAlpha = 0.01; let stepCount = 0; ctx.beginPath(); ctx.strokeStyle = stPoint.color; ctx.moveTo(stPoint.x, stPoint.y); setTimeout(drawStep, 10); function drawStep() { if (stepCount >= steps) { return; } ctx.moveTo(stPoint.x, stPoint.y); const direction = Math.random() < 0.5 ? -1 : 1; stPoint.y = stepSize * direction; stPoint.x = startX stepCount * 2; ctx.lineTo(stPoint.x, stPoint.y); ctx.lineWidth = 1; ctx.stroke(); stepCount; requestAnimationFrame(drawStep); } } for(const color of colors) { const startPoint = new Point(color); drawRandomWalk(startPoint, numSteps); }</pre> <pre class="brush:html;toolbar:false;"><canvas id="myCanvas" width="600" height="600"></canvas></pre> <p><br /></p>
P粉605385621P粉605385621528 days ago521

reply all(1)I'll reply

  • P粉327903045

    P粉3279030452023-08-02 00:56:35

    The problem is that every "pen" that draws a line shares state - you are drawing a long path made of many moves/lines, over and over again.

    If you want the globalAlpha gradient effect (which relies on being able to draw lines over and over again), you need to trace each pen draw individually and draw it as shown below.

    I removed the Point structure since it's not really needed.


    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    
    const numSteps = ctx.canvas.width / 2 + 10;
    const stepSize = 10;
    const startX = 0;
    const startY = canvas.height / 2;
    const timeInterval = 15;
    
    const colors = [
      '#FF1493', // Pink
      '#FF00FF', // Magenta
      '#800080', // Purple
      '#4B0082', // Indigo
      '#0000FF', // Blue
      '#00FFFF', // Cyan
      '#00FF00', // Green
      '#FFFF00', // Yellow
      '#FF7F00', // Orange
      '#8B4513'  // Saddle Brown
    ];
    
    
    
    function drawRandomWalk(startX, startY, color, nSteps) {
      setTimeout(drawStep, 10);
      const steps = [[startX, startY]];
      
      function drawStep() {
        if (steps.length >= nSteps) {
          return;
        }
        // Draw current line
        ctx.globalAlpha = 0.01;
        ctx.beginPath();
        ctx.strokeStyle = color;
        ctx.lineWidth = 1;
        let x = 0, y = 0;
        for(let i = 0; i < steps.length; i++) {
          [x, y] = steps[i];
          if(i === 0) ctx.moveTo(x, y);
          else ctx.lineTo(x, y);
        }
        ctx.stroke();
        // Compute next point
        const direction = Math.random() < 0.5 ? -1 : 1;
        y += stepSize * direction;
        x = startX + steps.length * 2; 
        steps.push([x, y]);
        requestAnimationFrame(drawStep);
      }
    }
    
    for(const color of colors)
    {
      drawRandomWalk(startX, startY, color, numSteps);
    }
    <canvas id="myCanvas" width="600" height="600"></canvas>


    reply
    0
  • Cancelreply