javascript - d3 js - 如何在不带频闪效果的情况下使用 fillStyle() 和 fillRect() 上的随机不透明度来模拟距离/景深?

标签 javascript canvas d3.js

我尝试使用 keywordsDepthBlur() 代替“雪花”的不透明度 - 它位于步骤函数内,但它会产生不需要的频闪效果 - 为什么?考虑以下代码,

编辑澄清:

<canvas id="canvas"></canvas>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var num = 2000;

var canvas = document.getElementById("canvas");
var width = canvas.width = 960;
var height = canvas.height = 500;
var ctx = canvas.getContext("2d");

var particles = d3.range(num).map(function(i) {
  return [Math.round(width*Math.random()), Math.round(height*Math.random())];
});

function particlesDepthBlur(){ 
   return Math.random();
   console.log(Math.random());
}

function particlesDepthSize(){
   return Math.floor((Math.random()*4)+1);
}

d3.timer(step);

function step() {
  ctx.shadowBlur=0;
  ctx.shadowColor="";
  ctx.fillStyle = "rgba(0,0,0,"+particlesDepthBlur()+")";
  ctx.fillRect(0,0,width,height);
  ctx.shadowBlur=particlesDepthSize();
  ctx.shadowColor="white";
  ctx.fillStyle = "rgba(255,255,255,1)";
  particles.forEach(function(p) {
    p[0] += Math.round(2*Math.random()-1);
    p[1] += Math.round(2*Math.random()-1) + 2;
    if (p[0] < 0) p[0] = width;
    if (p[0] > width) p[0] = 0;
    if (p[1] < 0) p[1] = height;
    if (p[1] > height) p[1] = 0;
    drawPoint(p);
  });
};

function drawPoint(p) {
  ctx.fillRect(p[0],p[1],1,1);
};
</script>
<style>
html, body { margin: 0; padding: 0; }
</style>

最佳答案

几件事:
首先,您在填充 Canvas 背景之前立即调用 ctx.fillStyle = "rgba(0,0,0,"+articlesDepthBlur()+")";
其次,您只计算每帧一次的模糊和不透明度,而不是每个粒子。
第三,如果您按粒子计算(并继续使用 Math.random()),那么它会导致我的机器每秒执行数千次操作。

这是我的

fiddle!

~每一帧我都会计算 10 个不透明度和 10 个尺寸,并在每个粒子上迭代设置它们。~ << 这是一个 old version ;现在,不透明度已在调用 step() 之前设置完毕,并且大小与不透明度成正比。

编辑:随机向下运动做得很好!
edit2:调整以设置每个粒子的恒定不透明度和大小。这对我来说仍然运行得很慢,可能是因为你每帧运行 Math.random() 4000 次。您可能会考虑每帧计算一次几十个位置向量,然后迭代所有粒子。这样,每片 n 片雪花都会以相同的模式落下,从而减少所需的计算量。

最后,也许可以考虑让“近处”的雪花(又大又亮)比“远处”的雪花落得更快。

<snip>
// Set up an opacity value for each particle, this will later be indexed with j
var particleOpacities = [];
particles.forEach(function(p){
  particleOpacities.push(particlesDepthBlur());
});

d3.timer(step);
var j = 0;
// since j is used by both step and drawPoint, it has to be outside both functions
function step() {
  ctx.shadowBlur=0;
  ctx.shadowColor="";
  ctx.fillStyle = "rgba(0,0,0,1)";
  ctx.fillRect(0,0,width,height);
  j = 0;
  particles.forEach(function(p) {
    p[0] += Math.round(2*Math.random()-1);
    p[1] += Math.round(2*Math.random()-1) + 2;
    if (p[0] < 0) p[0] = width;
    if (p[0] > width) p[0] = 0;
    if (p[1] < 0) p[1] = height;
    if (p[1] > height) p[1] = 0;
    drawPoint(p);
  });
};

function drawPoint(p) {
  j++; // iterate over points
  var particleSize = particleOpacities[j] * 4;
  ctx.shadowBlur=particleSize;
  ctx.shadowColor="white";
  ctx.fillStyle = "rgba(255,255,255," + particleOpacities[j] + ")";
  ctx.fillRect(p[0],p[1],particleSize,particleSize);
};

关于javascript - d3 js - 如何在不带频闪效果的情况下使用 fillStyle() 和 fillRect() 上的随机不透明度来模拟距离/景深?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19284441/

相关文章:

javascript - 我是否需要学习 CSS3 和 HTML 基础知识才能制作 HTML5 游戏和动态 Web 应用程序?

java - 将 Canvas 的内容发送到 Java 服务器并将其保存为图像

javascript - 动态启动/停止 d3.force

javascript - Django + Jquery + Ajax + D3 不起作用

javascript - 使用 Javascript 根据另一个选择的值更改一个选择

javascript - firebase.js :1 Uncaught (in promise) Error: Reference. 设置失败:第一个参数包含属性中的未定义

javascript - 启用识别连续语音

javascript - 如何使用jquery排除子元素选择器中的子元素?

javascript - 在图像上绘制 4 条直线(叠加)

javascript - D3 中 jQuery 的 $ (".cell:first") 是什么?