Suppose there is such an animation function requirement: change the width of a div from 100px to 200px. The code written may look like this:
animate1(document.getElementById('test1'), 200, 1000);
Is there a better way? Let’s take a look at a primary school math problem:
The inspiration brought by this question is that the distance at a certain moment can be calculated through a specific formula. In the same way, the value at a certain moment during the animation process can also be calculated through a formula instead of accumulating:
var timerId = setInterval(function() {
var percentage = (new Date - startTime) / duration;
var stepValue = startValue (endValue - startValue) * percentage;
element.style.width = stepValue 'px';
if (percentage >= 1) {
clearInterval(timerId);
element.innerHTML = new Date - startTime;
}
}, 13);
}
animate2(document.getElementById('test2'), 200, 1000);
After this improvement, you can see that the animation execution time will only have an error of 10 ms at most. But the problem has not been completely solved. Checking the test2 element in the browser development tool shows that the final width of test2 may be more than 200px. Careful inspection of the code of the animate2 function reveals:
The value of 1.percentage may be greater than 1, which can be solved by limiting the maximum value through Math.min.
2. Even if it is guaranteed that the value of percentage is not greater than 1, as long as endValue or startValue is a decimal, the value of (endValue - startValue) * percentage may still produce errors because the precision of Javascript decimal operations is not enough. In fact, what we want to ensure is the accuracy of the final value, so when the percentage is 1, just use endValue directly.
So, the code of animate2 function is modified to:
var timerId = setInterval(function() {
// Ensure that the percentage is not greater than 1
var percentage = Math.min(1, (new Date - startTime) / duration);
var stepValue;
If (percentage >= 1) {
// Ensure the accuracy of the final value
stepValue = endValue;
} else {
stepValue = startValue (endValue - startValue) * percentage;
}
element.style.width = stepValue 'px';
if (percentage >= 1) {
clearInterval(timerId);
element.innerHTML = new Date - startTime;
}
}, 13);
}
There is one last question: Why is the interval of setInterval set to 13ms? The reason is that the refresh rate of current monitors generally does not exceed 75Hz (that is, refreshed 75 times per second, that is, refreshed every about 13ms). It is better to synchronize the interval with the refresh rate.