使用requestAnimationFrame()时交替更改ctx.strokeStyle。

huangapple go评论82阅读模式
英文:

Alternating ctx.strokeStyle while using requestAnimationFrame()

问题

以下是您要翻译的内容:

"I'm trying to draw simple random motion as my landing page's background canvas, and I'm having a hard time getting the lines to have unique colors.

I've tried changing it after the moveTo as well, but didn't have success (just appeared to be a mix of the colors).

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);
}
<canvas id="myCanvas" width="600" height="600"></canvas>

"

英文:

I'm trying to draw simple random motion as my landing page's background canvas, and I'm having a hard time getting the lines to have unique colors.

I've tried changing it after the moveTo as well, but didnt have success (just appeared to be a mix of the colors).

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const canvas = document.getElementById(&#39;myCanvas&#39;);
const ctx = canvas.getContext(&#39;2d&#39;);
//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 = [
&#39;#FF1493&#39;, // Pink
&#39;#FF00FF&#39;, // Magenta
&#39;#800080&#39;, // Purple
&#39;#4B0082&#39;, // Indigo
&#39;#0000FF&#39;, // Blue
&#39;#00FFFF&#39;, // Cyan
&#39;#00FF00&#39;, // Green
&#39;#FFFF00&#39;, // Yellow
&#39;#FF7F00&#39;, // Orange
&#39;#8B4513&#39;  // 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 &gt;= steps) {
return;
}
ctx.moveTo(stPoint.x, stPoint.y);
const direction = Math.random() &lt; 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);
}

<!-- language: lang-html -->

&lt;canvas id=&quot;myCanvas&quot; width=&quot;600&quot; height=&quot;600&quot;&gt;&lt;/canvas&gt;

<!-- end snippet -->

答案1

得分: 0

问题在于每支“笔”绘制线条时都共享状态 - 你正在绘制一个由许多movetos/linetos组成的单一长路径,一次又一次地绘制它。

如果你想要globalAlpha淡入效果(它依赖于能够一次又一次地绘制线条),你需要分别跟踪每支笔所绘制的路径,并像下面这样绘制它。

我去掉了Point结构,因为它实际上不是必需的。

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>

你只需要复制上述的代码,然后粘贴到你的项目中即可。

英文:

The issue is each of the "pens" drawing the lines are sharing state – you're drawing a single long path that consists of many movetos/linetos over and over and again.

If you want the globalAlpha fade effect (which relies on being able to draw the line over and over again), you'll need to separately keep track of the trail drawn by each pen, and draw it, like below.

I got rid of the Point structure, since it's not really needed.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const canvas = document.getElementById(&#39;myCanvas&#39;);
const ctx = canvas.getContext(&#39;2d&#39;);
const numSteps = ctx.canvas.width / 2 + 10;
const stepSize = 10;
const startX = 0;
const startY = canvas.height / 2;
const timeInterval = 15;
const colors = [
&#39;#FF1493&#39;, // Pink
&#39;#FF00FF&#39;, // Magenta
&#39;#800080&#39;, // Purple
&#39;#4B0082&#39;, // Indigo
&#39;#0000FF&#39;, // Blue
&#39;#00FFFF&#39;, // Cyan
&#39;#00FF00&#39;, // Green
&#39;#FFFF00&#39;, // Yellow
&#39;#FF7F00&#39;, // Orange
&#39;#8B4513&#39;  // Saddle Brown
];
function drawRandomWalk(startX, startY, color, nSteps) {
setTimeout(drawStep, 10);
const steps = [[startX, startY]];
function drawStep() {
if (steps.length &gt;= 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 &lt; 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() &lt; 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);
}

<!-- language: lang-html -->

&lt;canvas id=&quot;myCanvas&quot; width=&quot;600&quot; height=&quot;600&quot;&gt;&lt;/canvas&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月31日 19:39:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803243.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定