Skip to content

Instantly share code, notes, and snippets.

@benfrain
Last active February 7, 2019 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benfrain/f7a9591b9db3f81bd6f6f34975d9cf80 to your computer and use it in GitHub Desktop.
Save benfrain/f7a9591b9db3f81bd6f6f34975d9cf80 to your computer and use it in GitHub Desktop.
JS utility to animate numeric values from one value to another
/**
* [animateNumericValues interpolates from one number to another with a max of 60 integers per second]
* @param {Element} element [The DOM element that will get interpolated]
* @param {number} fromValue [the first value]
* @param {number} toValue [the final value]
* @param {number} speed [how long the animation should take in milliseconds]
* @param {delay} delay [any delay before it starts counting up]
* @param {string} appendString [optional string that gets appended to the value. E.g. "%"]
*/
function animateNumericValues({
element = document.body,
fromValue = 0,
toValue = 0,
speed = 1000,
delay = 0,
format = {},
appendString = "",
} = {}) {
// Ensure the numbers compute
if (fromValue > toValue || toValue < 1) {
console.warn("The from value is greater than than the too value or the toValue is less than 1");
return;
}
// Create an array of all values between and including from and to
var arrayOfValuesFromTo = [];
for (let i = fromValue; i++ <= toValue; ) {
arrayOfValuesFromTo.push(i);
}
// Timing adjuster
let adjuster = speed / 1000;
// Reduce the number of items to around 60
let reduceToSixty = arrayOfValuesFromTo.reduce((arr, idx, elem, original) => {
if (original.length <= 30) {
arr.push(elem);
return arr;
}
// We always want the first and last value
// Get the difference of from and to and divide by 60 and then push every one of those values into the array
if (idx === 1 || idx % Math.round((fromValue - toValue) / (10 * adjuster)) === 0) {
arr.push(elem);
}
// We want the actual value of the final one
if (idx === original.length) {
arr.push(toValue);
}
return arr;
}, []);
// Handle any delay
setTimeout(e => {
writeToDom();
}, delay);
function writeToDom() {
// Write the values into the DOM
reduceToSixty.forEach((num, count) => {
setTimeout(() => {
element.textContent = `${num.toLocaleString("en-US", format)}${appendString}`;
}, (speed / reduceToSixty.length) * count);
});
}
}
@benfrain
Copy link
Author

benfrain commented Feb 5, 2019

You might want to pass in another parameter for the toLocaleString to vary the lang format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment