There is a slight misunderstanding about the way timeouts work in the example code. Timeouts are asynchronous, meaning that they execute out of the normal order of execution. As a result, the lime green is shown immediately, and then at various times later the background is repeatedly changed to green; although, the only time the change is noticed is the first time as changing from green to green has no effect.
setTimeout creates a task, JavaScript in a browser is single threaded and will execute tasks through a task scheduler.
Using 1000 - 50 * i
from 0 to 19 in the approach shown in the question will result in timeouts being scheduled for execution. First at 1000, then at 950, etc. However, they are all scheduled at the exact same time. So there is no difference scheduling them in forward or reverse order as the only relevant metric used is the time. Essentially the result is that every 50 milliseconds, the background color is set to green in this example.
Unfortunately, tasks that get executed in the browser are not executed exactly on time, and using this will aim at 50 milliseconds per call, but due to Operating System scheduling and depending on the system in use the result could be wildly different.
This could have been done with an interval just as easily, where the interval used was 50 milliseconds (although it would still suffer from the aforementioned OS issue). That said, there is no acceleration being used there. A better approach here, since we are dealing with animation (the colors flashing) would be to instead use requestAnimationFrame
MDN.
requestAnimationFrame
will attempt to run your code at 60 frames per second, or roughly 16.6 milliseconds per frame (1000 milliseconds / 60 frames).
Given that the goal was acceleration, a rate could be put in place to ramp the flashing.
// 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);
})()
.test {
width: 300px;
height: 300px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>