现在已经很晚了,道格拉斯·克罗克福德生活的大脑部分已经关闭了。我尝试了一些事情,但没有按预期做的事情。
我有一个画布,我绘制了2行,然后在计时器上将它们淡出,但只有循环中的最后一行被淡出。这是我的小提琴,在JS中向下看50行,看看它的实际效果在右下方的窗格中拖动你的鼠标:
这是函数,基本上超时只得到循环中的最后一个值,我以前见过这个,我敢肯定,如果我不是那么神志不清,它可能会更简单。这是特别的功能:
function update()
{
var i;
this.context.lineWidth = BRUSH_SIZE;
this.context.strokeStyle = "rgba(" + COLOR[0] + ", " + COLOR[1] + ", " + COLOR[2] + ", " + BRUSH_PRESSURE + ")";
for (i = 0; i < scope.painters.length; i++)
{
scope.context.beginPath();
var dx = scope.painters[i].dx;
var dy = scope.painters[i].dy;
scope.context.moveTo(dx, dy);
var dx1 = scope.painters[i].ax = (scope.painters[i].ax + (scope.painters[i].dx - scope.mouseX) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dx -= dx1;
var dx2 = scope.painters[i].dx;
var dy1 = scope.painters[i].ay = (scope.painters[i].ay + (scope.painters[i].dy - scope.mouseY) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dy -= dy1;
var dy2 = scope.painters[i].dy;
scope.context.lineTo(dx2, dy2);
scope.context.stroke();
for(j=FADESTEPS;j>0;j--)
{
setTimeout(function()
{
var x=dx,y=dy,x2=dx2,y2=dy2;
scope.context.beginPath();
scope.context.lineWidth=BRUSH_SIZE+1;
scope.context.moveTo(x, y);
scope.context.strokeStyle = "rgba(" + 255 + ", " + 255 + ", " + 255 + ", " + .3 + ")";
scope.context.lineTo(x2, y2);
scope.context.stroke();
scope.context.lineWidth=BRUSH_SIZE;
},
DURATION/j);
}
}
}
答案 0 :(得分:2)
问题是您在传递给dx
的函数中引用的变量dy
,setTimeout()
等是在周围范围内定义的,并且是在任何时候定义的超时实际上运行这些变量都保存了循环的最后一次迭代的值。
您需要创建一个额外的包含函数来关闭每次迭代的值。尝试以下内容:
for(j=FADESTEPS;j>0;j--) {
(function(x,y,x2,y2) {
setTimeout(function() {
scope.context.beginPath();
scope.context.lineWidth=BRUSH_SIZE+1;
scope.context.moveTo(x, y);
scope.context.strokeStyle = "rgba(" + 255 + ", " + 255 + ", " + 255 + ", " + .3 + ")";
scope.context.lineTo(x2, y2);
scope.context.stroke();
scope.context.lineWidth=BRUSH_SIZE;
},
DURATION/j);
})(dx, dy, dx2, dy2);
}
这将为j=FADESTEPS
循环的每次迭代创建一个新的匿名函数,立即执行它并传递dx
等值,就像循环的每次迭代运行时一样,并且将x
,y
等变量移出现有函数并将其作为新变量的参数,然后在超时运行时将使用正确的值。
答案 1 :(得分:1)
您可以尝试这样的事情:
`<script>
for(j=10;j>0;j--)
{
var fn = function(ind){return function()
{
console.log(ind);
};
}(j);
setTimeout(fn,
1000);
}
</script>`
答案 2 :(得分:0)
或者另一种方式(一旦你不使用IE,但首先让它学习画布:))
for(j=FADESTEPS;j>0;j--)
{
setTimeout(function(x,y,x2,y2)
{
scope.context.beginPath();
scope.context.lineWidth=BRUSH_SIZE+1;
scope.context.moveTo(x, y);
scope.context.strokeStyle = "rgba(" + 255 + ", " + 255 + ", " + 255 + ", " + .3 + ")";
scope.context.lineTo(x2, y2);
scope.context.stroke();
scope.context.lineWidth=BRUSH_SIZE;
},
DURATION/j,dx,dy,dx2,dy2);
}
ps:没有必要设置额外的功能(原因很清楚)
答案 3 :(得分:0)
j
是全球性的。closePath()
beginPath()
<强>解释强>
关于dx
和dy
从更高范围传递的其他答案是正确的答案。同步for循环中定义的异步函数将采用该状态的最后一个版本。
for (var i = 0; i < 10; i++) setTimeout(function() { console.log(i)}, 10 )
10
10
// ...
答案 4 :(得分:0)
我建议你使用一个数组并在循环中存储避免setTimeOut
调用的点。有点像这样。
this.interval = setInterval(update, REFRESH_RATE);
var _points = [];
function update() {
var i;
this.context.lineWidth = BRUSH_SIZE;
this.context.strokeStyle = "rgba(" + COLOR[0] + ", " + COLOR[1] + ", " + COLOR[2] + ", " + BRUSH_PRESSURE + ")";
for (i = 0; i < scope.painters.length; i++) {
scope.context.beginPath();
var dx = scope.painters[i].dx;
var dy = scope.painters[i].dy;
scope.context.moveTo(dx, dy);
var dx1 = scope.painters[i].ax = (scope.painters[i].ax + (scope.painters[i].dx - scope.mouseX) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dx -= dx1;
var dx2 = scope.painters[i].dx;
var dy1 = scope.painters[i].ay = (scope.painters[i].ay + (scope.painters[i].dy - scope.mouseY) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dy -= dy1;
var dy2 = scope.painters[i].dy;
scope.context.lineTo(dx2, dy2);
scope.context.stroke();
_points.push([dx, dy, dx2, dy2]);
clear();
}
}
function clear(){
if(_points.length < FADESTEPS){
return;
}
var p = _points.shift();
if(!p){
return;
}
var x = p[0],
y = p[1],
x2 = p[2],
y2 = p[3];
scope.context.beginPath();
scope.context.lineWidth = BRUSH_SIZE + 1;
scope.context.moveTo(x, y);
scope.context.strokeStyle = "rgba(" + 255 + ", " + 255 + ", " + 255 + ", " + .3 + ")";
scope.context.lineTo(x2, y2);
scope.context.stroke();
scope.context.lineWidth = BRUSH_SIZE;
}
我知道这不是你所需要的,但我认为可以修改它以获得它。