我有一个test
课程,background-color
我希望在lime
和green
之间更快更快地翻转。
为此,我使用for循环变量并将其传递给包含setTimeout()
的函数,但它不起作用。
(这不是一个重复的问题。所说的"原文"是一个简单的setTimeout()
,而这个问题是关于for循环中的setTimeout()
。我明白这个问题的答案可能会间接回答我的问题,但问题本身并不相同)
$(document).ready(function() {
for (var i = 0; i < 20; i++) {
delay(i);
$(".test").css('background-color', 'lime');
}
});
function delay(i) {
setTimeout(function() {
$(".test").css('background-color', 'green');
}, 1000 - 50 * i);
}
&#13;
.test {
width: 300px;
height: 300px
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>
&#13;
答案 0 :(得分:1)
问题是循环执行速度超过超时。 setTimeout函数基本上表示在一定时间后执行给定的函数。你在那里创建的for循环将继续,而不是等待setTimeout函数内的代码被执行,换句话说,你的代码产生了将在未来执行的20个函数。
有很多方法可以生成您需要的功能。 为了保持简单并解决它,你应该创建两个函数:
$(document).ready(function() {
for (var i = 0; i < 20; i++) {
delay_lime(i);
delay_green(i+1);
}
});
function delay_green(i) {
setTimeout(function() {
$(".test").css('background-color', 'green');
}, 1000 - 50 * i);
}
function delay_lime(i) {
setTimeout(function() {
$(".test").css('background-color', 'lime');
}, 1000 - 50 * i);
}
答案 1 :(得分:1)
尝试这种方式:
for(var i=0;i<20;i++)
{
delay(i);
}
function delay(i) {
setTimeout(function() {
if (i%2 == 0) {
$(".test").css('background-color', 'green');
} else {
$(".test").css('background-color', 'lime');
}
}, 1000 - 50 * i);
}
答案 2 :(得分:1)
试试这个:这是一个例子example
$(document).ready(function() {
delay();
var start = 0;
delay(start);
function delay(start) {
setTimeout(function() {
if(start == 0 ){
$(".test").css('background-color', 'green');
start = 1;
}else{
$(".test").css('background-color', 'red');
start = 0;
}
delay(start);
}, 100);
}
});
答案 3 :(得分:0)
如果您想使用for
循环,则应将其包含的函数转换为async
函数,并在所需时间解析await
个承诺:
const delay = (i) => new Promise(resolve => {
setTimeout(resolve, 1000 - 50 * i);
});
function changeToGreen() {
$(".test").css('background-color', 'green');
}
function changeToLime() {
$(".test").css('background-color', 'lime');
}
(async () => {
for (var i = 0; i < 20; i++) {
await delay(i);
changeToLime();
await delay(i);
changeToGreen();
}
})();
答案 4 :(得分:0)
你的循环不会等待任何超时发生,它会运行并排队以相关间隔触发的事件。
然而,在这样做时,它会将背景颜色设置为灰色多次。
循环结束后,排队的间隔开始触发,并将背景颜色设置为绿色多次。
但是颜色不会交替,因为代码执行不符合您的预期。
此外,对setInterval的多次调用将在指定的延迟之后对要触发的事件进行排队。代码不会等待分配的时间,然后触发下一个。所以你的1000 - 50 *我实际上可以先排队最新的事件,依此类推,直到排队实际上先发射的事件为止。那有意义吗?您可以更直观地按照它们将触发的顺序设置它们。您可以通过将超时增加一个减少的变量来实现减少延迟,例如
time = 1000;
delay = 1000;
setTimeout (blah, time);
time += delay;
delay -= 50;
setTimeout (blah, time);
// etc.
您可以通过将备用间隔设置为绿色和石灰来实现交替效果。为此,一个简单的切换变量会有所帮助。
color = 1;
color = 1 - color; // toggles between 0 and 1
useColor = ["lime", "green"][color];
我没有为您重写整个程序,但如果您有具体问题,我可以提供更多帮助。学习的最佳方式是做。
答案 5 :(得分:0)
对示例代码中超时的工作方式存在轻微的误解。超时是异步的,这意味着它们执行超出正常的执行顺序。结果,立即显示柠檬绿,然后在不同时间后,背景重复变为绿色;虽然,唯一一次注意到变化是第一次从绿色变为绿色没有效果。
setTimeout创建一个任务,浏览器中的JavaScript是单线程的,并将通过任务调度程序执行任务。
在问题中显示的方法中使用0到19之间的1000 - 50 * i
将导致计划执行超时。首先是1000,然后是950,等等。但是,它们都安排在同一时间。因此,以正向或反向顺序排列它们没有区别,因为使用的唯一相关度量是时间。基本上结果是每50毫秒,在这个例子中背景颜色设置为绿色。
不幸的是,在浏览器中执行的任务没有准确执行,并且使用它将针对每次调用50毫秒,但由于操作系统调度并且取决于使用的系统,结果可能会大不相同。
这可以用一个间隔来完成,其中使用的间隔是50毫秒(尽管它仍然会受到上述OS问题的影响)。也就是说,那里没有使用加速。这里有一个更好的方法,因为我们处理动画(颜色闪烁)将改为使用 requestAnimationFrame
MDN 。
requestAnimationFrame
将尝试以每秒60帧的速度运行您的代码,或者每帧大约16.6毫秒(1000毫秒/ 60帧)。
鉴于目标是加速,可以采取措施来加速闪光。
// Cache the constructed jQuery object for element with class "test"
var testCache = $('.test');
// Create a set of colors to use in the flashing
var colors = ['lime','green'];
// Use a variable for a switch between the two colors
var colorSwitch = 0;
// Keep track of how many times the color has flashed
var i = 0;
// Used for tracking the start of an animation sequence
var start;
// In order to facilitate acceleration, use a function for
// determining the time between flashes,
// used an offset x^2 line at (20,16) with a 2x width
// y = 1/2(x-19)^2 - 19x + 16
var ft = t => 0.5*(t-19)*(t-19) - (t-19) + 16;
// This function will be called every 16.6 milliseconds
// by requestAnimationFrame, the timestamp is automatically injected
(function flashAccel(timestamp){
// Loop control to ensure only 20 flashes occur
if(i >= 20) return;
// Track the start of the timing for the animation sequence
start = start || timestamp;
// This is the milliseconds since the last sequence was updated
var elapsed = timestamp - start;
// Check to see if enough time has elapsed based on the acceleration
// function's value and the current value, if it has then update the view
if( elapsed > ft(i) ){
// Swaps between 0 and 1
colorSwitch = 1 - colorSwitch;
// Selects 0 or 1 indexed color
var color = colors[colorSwitch];
testCache.css('background-color',color);
// Update metrics
i++;
start = timestamp;
}
// Request the function to be called again in roughly 16.6 milliseconds
window.requestAnimationFrame(flashAccel);
})()
&#13;
.test {
width: 300px;
height: 300px
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>
&#13;