Skip to content

Instantly share code, notes, and snippets.

@ianpgall
Last active August 29, 2015 14:05
Show Gist options
  • Save ianpgall/20c75181dd9b7db6aef8 to your computer and use it in GitHub Desktop.
Save ianpgall/20c75181dd9b7db6aef8 to your computer and use it in GitHub Desktop.
JavaScript function that animates an element's style or property
function animate(element, options) {
"use strict";
/*
* Options:
* style - a numerical style property to animate
* property - a numerical property to animate
* endValue - the value to animate to
* unit - (optional) the value's units; defaults to ""
* duration - (optional) how long, in milliseconds, for the animation to complete; defaults to 400
* complete - (optional) a function to call when the animation completes
*/
var style, property,
startValue, endValue, unit,
duration, completeCallback,
getProgress, getNextValue,
valueChanger, iterator,
startTime;
// Make sure the element is provided
if (!element) {
throw new ReferenceError("element is not defined");
}
style = options.style;
property = options.property;
// Make sure the style OR property is provided
if (!style && !property) {
throw new TypeError("style/property is invalid");
}
// Make sure the endValue is provided
if (options.endValue === null || options.endValue === undefined) {
throw new TypeError("endValue is invalid");
}
// Set the startValue based on the element's current style/property
if (style) {
startValue = parseFloat(getComputedStyle(element)[style]);
} else if (property) {
startValue = parseFloat(element[property]);
}
endValue = parseFloat(options.endValue);
unit = "" + (options.unit || "");
duration = +options.duration || 400;
completeCallback = options.complete;
// Determines the progress of the animation (from 0 to 1)
getProgress = function () {
return Math.min(1, (new Date().getTime() - startTime) / duration);
};
// Determines the next value to set for the style/property
getNextValue = (function () {
var valueDifference = (endValue - startValue);
return function (progress) {
return (startValue + (progress * (valueDifference))) + unit;
};
}());
// Set the function that changes the value on each animation step
if (style) {
valueChanger = function (nextValue) {
element.style[style] = nextValue;
};
} else if (property) {
valueChanger = function (nextValue) {
element[property] = nextValue;
};
}
// Main animation logic
iterator = function () {
var progress, nextValue;
// Set next value
progress = getProgress();
nextValue = getNextValue(progress);
valueChanger(nextValue);
// Check if animation is done
if (progress === 1) {
// Check if callback for completion is provided
if (completeCallback) {
completeCallback();
}
return;
}
// Continue animation if not done
setTimeout(iterator, 15);
};
// Start animating
startTime = new Date().getTime();
iterator();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment