我尝试使用 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/