d3 js - 如何在没有频闪效果的情况下,在fillStyle()和fillRect()上使用随机不透明度来模拟距离/
d3 js - how to mimic distance/depth of field using randomized opacity on fillStyle() & fillRect() without strobe effect?
我试图使用粒子DepthBlur((代替"雪花"的不透明度 - 它位于步进函数内部,但它会产生不希望的频闪效果 - 为什么?考虑以下代码,
为澄清而编辑:
<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>
几件事:
首先,您在填充画布背景之前立即调用ctx.fillStyle = "rgba(0,0,0,"+particlesDepthBlur()+")";
。
其次,您每帧只计算一次模糊和不透明度,而不是每个粒子。
第三,如果你计算每个粒子(并继续使用Math.random()
(,那么它会使我的机器陷入每秒数千次操作的困境。
这是我的
小提琴!
~每帧我计算 10 个不透明度和 10 个大小,并迭代粒子,设置每个粒子~ <<这是一个旧版本;现在,在调用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);
};
ctx.fillStyle = "rgba(0,0,0,"+particlesDepthBlur()+")";
随机更改上一个画布的可见程度。它在整个画布上均匀地执行此操作。有时,如果用黑色完全填充屏幕,擦除过去的视图,有时它会让最后一个屏幕部分显示。当它允许看到以前的视图时,它可以使画布上的白色数量增加一倍,并且当随后是低不透明度时,白色的数量突然下降。
function particlesDepthBlur(){
return Math.random(0.5)+.5;
}
平滑了这个问题
- $(document).height()在刷新时随机化值(Safari 5.1.10)
- 使用当前日期生成随机id
- 从a-z中随机选择一个字母
- RequireJ无法随机加载脚本
- 单击按钮时显示随机字符串
- Ajax更新面板随机错误'PRM_MissingPanel'
- 如何检查if/else语句中的随机条件
- 是否可以自动拉取“随机”;标签“;从一长串文本中提取
- 如何使用D3生成特定范围内的随机颜色
- 如何在 Javascript/jQuery 中获取一些随机下拉列表的选定值
- 在固定位置显示随机图像
- 有效地获取两个区间之间的随机整数
- 如何获得随机灯光颜色
- 设置随机数,然后每5秒随机减少一次,直到达到0(javascript)
- 阵列中随机图像的问题
- 显示数字,然后每5秒随机更改一次(javascript)
- 使用JS按顺序显示图像,而不是随机显示
- 使用javascript和随机暂停/超时快速循环文本
- d3 js - 如何在没有频闪效果的情况下,在fillStyle()和fillRect()上使用随机不透明度来模拟距离/
- 在HTML5 Canvas中随机化RGB,使用Javascript为每个fillRect设置一个新值