有没有一种方法在HTML5画布上绘制“流光”(逐渐消失的“数字荧光”效果)?

3
我想在HTML5画布上绘制一个移动的点,它沿着复杂的轨迹运动。我知道如何实现这一点;例如,可以看到下面实现的Lorenz attractor。但是对于小点来说,很难跟踪。 有没有办法在点后面添加模糊的轨迹? 我可以保留绘制点的过去历史记录,我只是不知道如何使它们逐渐消失。

从技术角度来看,我认为这将是一条多段线/曲线,其中透明度/宽度/颜色沿着曲线平滑变化。我知道如何绘制多段线(如果需要,可以弄清楚贝塞尔曲线),但我不知道如何沿着路径应用平滑渐变。

(数字示波器通过具有数字荧光示波器效果来解决了这个“问题”,其中示波器模拟了旧的模拟“荧光体”效果:被示波器“束”击中的区域需要一段时间才能消失。)

<!DOCTYPE html>
<html>
<head><script type="text/javascript">
  document.addEventListener("DOMContentLoaded", function(event) {
 var x = 1, y = 0, z = 0, t=0;
 function onTick(timestamp)
 {
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.clearRect(0, 0, 300, 300);
  ctx.fillStyle = 'black';
  var cx = 150;
  var cy = 150;
  var r = 5;
  var now = timestamp * 0.001;
  var dt = now - t;
  t = now;
  if (dt > 0.1)
   dt = 0.1;
  // Lorenz attractor
  var sigma = 10, rho=28, beta=8/3;
  var dxdt = sigma*(y-x);
  var dydt = x*(rho-z)-y;
  var dzdt = x*y-beta*z;
  x += dt*dxdt;
  y += dt*dydt;
  z += dt*dzdt;
  
  var drawx = cx + r*x;
  var drawy = cy + r*y;
  var rdot = 2;
  ctx.beginPath();
  ctx.arc(drawx, drawy, rdot, 0, 2 * Math.PI, true);
  ctx.fill();
  requestAnimationFrame(onTick);  
 }
 requestAnimationFrame(onTick);
  });
</script></head>
<body>
  <canvas id="canvas" width="300" height="300"/>
  </body>
</html>


我认为我会使用的技术是保留所有过去位置的数组,然后将该数组用作绘制和绘制点到画布的手段,这样,您可以完全控制每个点的不透明度(“领先”点最暗,而所有“跟随者”点越往下线越透明... - radiovisual
请不要在没有阅读问题的情况下随意添加标签。 “绘画技巧”并不真正与动画有关,因为它可以静态地显示。 - Jason S
@radiovisual 是的,我有类似的想法...问题是(我将在我的问题中重新阐述),我不知道如何沿着曲线绘制具有颜色/不透明度/宽度渐变的折线/曲线。 - Jason S
2个回答

3

不要在每一帧清除矩形,只需要在alpha通道中涂上颜色,暂时保存之前的点。我用fillRect替换了你的clearRect,并将fillStyle设置为白色透明。

请记住你可以调整alpha通道,这样可以让点保留更长或更短的时间。在我的代码中,这是ctx.fillStyle = "rgba(255, 255, 255, 0.04)";中的0.04。我只是将它调低以使这些轨迹保持更长时间。

document.addEventListener("DOMContentLoaded", function(event) {
 var x = 1, y = 0, z = 0, t=0;
 function onTick(timestamp)
 {
  var ctx = document.getElementById('canvas').getContext('2d');
  //ctx.clearRect(0, 0, 300, 300);
        ctx.fillStyle = "rgba(255, 255, 255, 0.04)";
        ctx.fillRect(0, 0, 300, 300);
  ctx.fillStyle = 'black';
  var cx = 150;
  var cy = 150;
  var r = 5;
  var now = timestamp * 0.001;
  var dt = now - t;
  t = now;
  if (dt > 0.1)
   dt = 0.1;
  // Lorenz attractor
  var sigma = 10, rho=28, beta=8/3;
  var dxdt = sigma*(y-x);
  var dydt = x*(rho-z)-y;
  var dzdt = x*y-beta*z;
  x += dt*dxdt;
  y += dt*dydt;
  z += dt*dzdt;
  
  var drawx = cx + r*x;
  var drawy = cy + r*y;
  var rdot = 2;
  ctx.beginPath();
  ctx.arc(drawx, drawy, rdot, 0, 2 * Math.PI, true);
  ctx.fill();
  requestAnimationFrame(onTick);  
 }
 requestAnimationFrame(onTick);
  });
canvas {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  z-index: -1;
}
<canvas id="canvas"></canvas>


哦,那很有创意! - Jason S
@JasonS 我重新阅读了问题,在你提供的链接中可以看到淡色线条,几乎像是点要跟随的轨迹。你需要这样吗?还是这种渐变效果可以?你可以调整 alpha 通道来使点停留更长/更短的时间。 - jeffery_the_wind
那是一个独立的效果;我知道如何绘制这些东西,我猜你需要做的是有两个画布元素,一个是“永久”的,另一个具有像你描述的淡出alpha效果。我想实际上我会做的是不是单个点,而是在最后两个点之间画一条线/曲线,然后应用像你所做的淡出效果。 - Jason S
是的,我只是在尝试一些东西,但还没有完全理解。 - jeffery_the_wind
@JasonS 是的,只需要增加 alpha 值就可以了。我觉得点点一直存在的效果很酷,但是如果将 alpha 值从 0.04 调高到 0.15 或更高,点点应该就会完全消失。我试着让“轨迹”在下面保持可见,但还没有成功:https://jsfiddle.net/nLj78zpd/ - jeffery_the_wind

0
经典的技巧是画折线而不是单个点,每个顶点的颜色和/或不透明度都改变,亮度最高的会沿着轨迹走得最远。

嗯...好,是的,我知道我想看什么(基本上就是你所说的),但我不知道怎样实现。 - Jason S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接