Comparing version 0.2.0 to 0.4.0
@@ -1,8 +0,5 @@ | ||
// imports | ||
var EasingFactory = require("./ease"), | ||
AnimatedElement = require("./element"), | ||
Helper = require("./helper"), | ||
Constant = require("./constants"); | ||
var EasingFactory = require("./ease"), | ||
Helper = require("./helper"), | ||
Constants = require("./constants"); | ||
var Animar = function() { | ||
@@ -13,41 +10,175 @@ this.elementMap = new Map(); | ||
Animar.prototype.add = function(element, attributes, options) { | ||
return this._add(element, attributes, options, { delay: 0, currentDuration: 0, totalDuration: 0, animationList: [] }); | ||
}; | ||
Animar.prototype.addAnimationToMap = function(args) | ||
{ | ||
if (!this.elementMap.has(args.element)) { | ||
this.elementMap.set(args.element, new AnimatedElement()); | ||
Animar.prototype._add = function(element, attributes, options, chainOptions) { | ||
var self = this; | ||
// manage options defaults | ||
options = options || {}; | ||
options.delay = options.delay || 0; | ||
for (var attribute in attributes) { | ||
/* istanbul ignore else */ | ||
if (attributes.hasOwnProperty(attribute)) { | ||
var start, destination; | ||
var attributeValue = attributes[attribute]; | ||
if (typeof attributeValue === 'number') { | ||
destination = attributeValue; | ||
} else { | ||
start = attributeValue[0]; | ||
destination = attributeValue[1]; | ||
} | ||
var attrOptions = { | ||
start: start, | ||
duration: options.duration, | ||
easing: options.easing, | ||
delay: options.delay + chainOptions.delay, | ||
loop: options.loop, | ||
damping: options.damping | ||
}; | ||
var currentAnimation = this._addAnimation(element, attribute, destination, attrOptions); | ||
chainOptions.animationList.push(currentAnimation); | ||
} | ||
} | ||
this.elementMap.get(args.element).addAnimation(args); | ||
chainOptions.currentDuration = Math.max(chainOptions.currentDuration, options.delay + options.duration); | ||
return { // chaining functions | ||
and: self._andChainFunction(chainOptions), | ||
then: self._thenChainFunction(chainOptions), | ||
loop: self._loopChainFunction(chainOptions) | ||
}; | ||
}; | ||
Animar.prototype._andChainFunction = function(chainOptions) { | ||
var self = this; | ||
return function(element, attributes, options) { | ||
return self._add(element, attributes, options, chainOptions); | ||
}; | ||
}; | ||
Animar.prototype.addAnimation = function(args) | ||
{ | ||
var element = args.element, | ||
attribute = args.attribute, | ||
destination = args.destination, | ||
duration = args.duration, | ||
easingFunction = args.easingFunction; | ||
Animar.prototype._thenChainFunction = function(chainOptions) { | ||
var self = this; // maintain reference to Animar instance through the forEach calls | ||
return function(element, attributes, options) { | ||
chainOptions.totalDuration = chainOptions.totalDuration + chainOptions.currentDuration; | ||
chainOptions.currentDuration = 0; | ||
chainOptions.delay = chainOptions.totalDuration; | ||
return self._add(element, attributes, options, chainOptions); | ||
}; | ||
}; | ||
if (typeof easingFunction === 'string') { | ||
easingFunction = EasingFactory[easingFunction](); | ||
} | ||
Animar.prototype._loopChainFunction = function(chainOptions) { | ||
return function() { | ||
chainOptions.totalDuration = chainOptions.totalDuration + chainOptions.currentDuration; | ||
for (var i = 0; i < chainOptions.animationList.length; i++) { | ||
var anim = chainOptions.animationList[i]; | ||
anim.loop = true; | ||
anim.wait = chainOptions.totalDuration - anim.delay - anim.totalIterations; | ||
} | ||
}; | ||
}; | ||
Animar.prototype._addAnimation = function(element, attribute, destination, options) { | ||
options = options || {}; | ||
// DEFAULTS & PARAMETER TRANSFORMATION | ||
options.damping = options.damping || 0.8; | ||
options.easing = options.easing || 'linear'; | ||
options.easing = typeof options.easing === 'string' ? | ||
(options.easing === 'elastic' ? EasingFactory[options.easing](options.damping) : EasingFactory[options.easing]()) : | ||
(options.easing); | ||
options.duration = options.duration || 60; | ||
options.loop = options.loop || false; | ||
options.delay = options.delay || 0; | ||
options.start = options.start === undefined ? Helper.getStartValue([element, attribute]) : options.start; | ||
options.wait = options.wait || 0; | ||
var newAnimation = { | ||
element: element, | ||
attribute: attribute, | ||
start: options.start, | ||
destination: destination, | ||
duration: duration, | ||
ease: easingFunction | ||
duration: options.duration, | ||
ease: options.easing, | ||
delay: options.delay, | ||
loop: options.loop, | ||
wait: options.wait | ||
}; | ||
this.addAnimationToMap(newAnimation); | ||
this.requestTick(); | ||
var currentAnimation = this._addAnimationToMap(newAnimation); | ||
this._requestTick(); | ||
return currentAnimation; | ||
}; | ||
Animar.prototype._addAnimationToMap = function(args) { | ||
if (!this.elementMap.has(args.element)) { | ||
this.elementMap.set(args.element, new Map()); | ||
} | ||
return this._addAnimationToElement(this.elementMap.get(args.element),args); | ||
}; | ||
Animar.prototype.calculateAnimationValue = function(animations) | ||
{ | ||
Animar.prototype._addAnimationToElement = function(attributeMap, args) { | ||
if (!attributeMap.has(args.attribute)) { | ||
attributeMap = this._createAttribute(attributeMap,args); | ||
} | ||
var currentAttribute = attributeMap.get(args.attribute), | ||
startValue = currentAttribute.model - args.destination, | ||
changeInValue = 0 - startValue; | ||
currentAttribute.model = args.destination; | ||
var currentAnimation = { | ||
currentIteration: 0 - args.delay, | ||
startValue: startValue, | ||
changeInValue: changeInValue, | ||
totalIterations: args.duration, | ||
easingFunction: args.ease, | ||
loop: args.loop, | ||
delay: args.delay, | ||
wait: args.wait | ||
}; | ||
currentAttribute.animations.push(currentAnimation); | ||
return currentAnimation; | ||
}; | ||
Animar.prototype._createAttribute = function(attributeMap, animation) { | ||
var newAttributeObject = { | ||
model: animation.start, | ||
animations: [] | ||
}; | ||
attributeMap.set(animation.attribute, newAttributeObject); | ||
return attributeMap; | ||
}; | ||
Animar.prototype._update = function() { | ||
var animationsRemaining = this._renderDOM(); | ||
this._stepFrame(); | ||
this.ticking = false; | ||
if (animationsRemaining) { | ||
this._requestTick(); | ||
} | ||
}; | ||
Animar.prototype._requestTick = function() { | ||
if (!this.ticking) { | ||
window.requestAnimationFrame(this._update.bind(this)); | ||
this.ticking = true; | ||
} | ||
}; | ||
Animar.prototype._calculateAnimationValue = function(animations) { | ||
var result = 0; | ||
animations.forEach(function(value) { | ||
result += value.easingFunction(value.currentIteration, value.startValue, value.changeInValue, value.totalIterations); | ||
var currentIteration = value.currentIteration; | ||
if (value.currentIteration < 0) { | ||
currentIteration = 0; | ||
} | ||
if (value.currentIteration >= value.totalIterations) { | ||
currentIteration = value.totalIterations; | ||
} | ||
result += value.easingFunction(currentIteration, value.startValue, value.changeInValue, value.totalIterations); | ||
}); | ||
@@ -57,4 +188,3 @@ return result; | ||
Animar.prototype.applyStyle = function(element, attribute, value) { | ||
Animar.prototype._applyStyle = function(element, attribute, value) { | ||
switch(attribute) { | ||
@@ -67,8 +197,11 @@ case("transform"): | ||
break; | ||
case("perspective"): | ||
element.style.perspective = value; | ||
element.style.webkitPerspective = value; | ||
break; | ||
} | ||
}; | ||
Animar.prototype.renderDOM = function() { | ||
var self = this; // maintain reference to Animar instance through the forEach calls | ||
Animar.prototype._renderDOM = function() { | ||
var self = this; | ||
var animated = false; | ||
@@ -78,30 +211,20 @@ self.elementMap.forEach(function(value, key) { | ||
var transformValue = ""; | ||
value.attributeMap.forEach(function(value, key) { | ||
animated = true; | ||
var targetAttribute = key; | ||
var targetValue = value.model + self.calculateAnimationValue(value.animations); | ||
if (Constant.TRANSFORM_ATTRIBUTES.indexOf(targetAttribute) !== -1) { | ||
switch(targetAttribute) { | ||
case("translateX"): | ||
transformValue += "translateX(" + targetValue + "px) "; | ||
break; | ||
case("translateY"): | ||
transformValue += "translateY(" + targetValue + "px) "; | ||
break; | ||
case("scaleX"): | ||
transformValue += "scaleX(" + targetValue + ") "; | ||
break; | ||
case("scaleY"): | ||
transformValue += "scaleY(" + targetValue + ") "; | ||
break; | ||
case("rotate"): | ||
transformValue += "rotate(" + targetValue + "deg) "; | ||
break; | ||
value.forEach(function(value, key) { | ||
var targetAttribute = String(key); | ||
if ( value.animations.length !== 0 ) { | ||
animated = true; | ||
var targetValue = value.model + self._calculateAnimationValue(value.animations), | ||
pxRegex = /(perspective)|(translate[XYZ])/, | ||
degRegex = /rotate[XYZ]?/; | ||
if (Constants.TRANSFORM_ATTRIBUTES.indexOf(targetAttribute) !== -1) { | ||
var unit = ((pxRegex.test(targetAttribute)) ? "px" : (degRegex.test(targetAttribute) ? "deg" : "")); | ||
transformValue += targetAttribute + "(" + targetValue + unit + ") "; | ||
} else { | ||
self._applyStyle(targetElement, targetAttribute, targetValue); | ||
} | ||
} else { | ||
self.applyStyle(targetElement, targetAttribute, targetValue); | ||
} | ||
}); | ||
if (transformValue !== "") { | ||
self.applyStyle(targetElement, "transform", transformValue); | ||
transformValue += "translateZ(0)"; | ||
self._applyStyle(targetElement, "transform", transformValue); | ||
} | ||
@@ -112,13 +235,14 @@ }); | ||
Animar.prototype.stepFrame = function() { | ||
Animar.prototype._stepFrame = function() { | ||
var elementMap = this.elementMap; | ||
elementMap.forEach(function(value) { | ||
var attributeMap = value.attributeMap; | ||
attributeMap.forEach(function(value) { | ||
value.forEach(function(value) { | ||
var updatedAnimations = []; | ||
value.animations.forEach(function(value) { | ||
if (value.currentIteration !== value.totalIterations) { | ||
if (value.currentIteration < (value.totalIterations + value.wait)) { | ||
value.currentIteration += 1; | ||
updatedAnimations.push(value); | ||
} else if (value.loop) { | ||
value.currentIteration = 0 - value.delay; | ||
updatedAnimations.push(value); | ||
} | ||
@@ -128,24 +252,5 @@ }); | ||
}); | ||
value.attributeMap = attributeMap; | ||
}); | ||
}; | ||
Animar.prototype.update = function() { | ||
var animationsRemaining = this.renderDOM(); | ||
this.stepFrame(); | ||
this.ticking = false; | ||
if (animationsRemaining) { this.requestTick(); } | ||
}; | ||
Animar.prototype.requestTick = function() { | ||
if (!this.ticking) { | ||
window.requestAnimationFrame(this.update.bind(this)); | ||
this.ticking = true; | ||
} | ||
}; | ||
module.exports = Animar; |
var Constants = { | ||
TRANSFORM_ATTRIBUTES: ["translateX", "translateY", "scaleX", "scaleY", "rotate"] | ||
TRANSFORM_ATTRIBUTES: ["translateX", "translateY", "translateZ", "scale", "scaleX", "scaleY", "rotate", "rotateX", "rotateY", "rotateZ"] | ||
}; | ||
module.exports = Constants; |
@@ -129,3 +129,3 @@ var EasingFactory = { | ||
}, | ||
circular_out: function() { | ||
circular_out: function() { | ||
return function(t, b, c, d) { | ||
@@ -137,3 +137,3 @@ t /= d; | ||
}, | ||
circular_in_out: function() { | ||
circular_in_out: function() { | ||
return function(t, b, c, d) { | ||
@@ -145,2 +145,22 @@ t /= d/2; | ||
}; | ||
}, | ||
elastic: function(damping) { | ||
return function(currentIteration, startValue, changeInValue, totalIterations) { | ||
if (damping >= 1) { | ||
damping = 0.99; | ||
} | ||
// prepare variables | ||
var iterationMult = 27.42078669 * Math.pow(damping, -0.8623276489); | ||
var startVelocity = 0.0, | ||
spring = 0.7, | ||
weightedIteration = currentIteration * (iterationMult / totalIterations); | ||
// Spring simulation | ||
var wd = spring * Math.sqrt(1.0 - Math.pow(damping, 2.0)); | ||
var theta = damping * spring; | ||
return Math.exp(-1.0 * theta * weightedIteration) * | ||
(startValue * Math.cos(wd * weightedIteration) + | ||
((theta * startValue + startVelocity) / wd) * Math.sin(wd * weightedIteration)); | ||
}; | ||
} | ||
@@ -147,0 +167,0 @@ }; |
@@ -49,6 +49,3 @@ var Helper = { | ||
var values = this.getTransformMatrix(element); | ||
var a = values[0], | ||
b = values[1]; | ||
return Math.round(Math.atan2(b, a) * (180/Math.PI)); | ||
return Math.round(Math.atan2(values[1], values[0]) * (180/Math.PI)); | ||
}, | ||
@@ -59,2 +56,30 @@ | ||
return parseFloat(computedStyle.getPropertyValue("opacity")); | ||
}, | ||
getStartValue: function(animation) { | ||
var result; | ||
switch(animation[1]) { | ||
case('opacity'): | ||
result = this.getOpacity(animation[0]); | ||
break; | ||
case('translateX'): | ||
result = this.getTranslateX(animation[0]); | ||
break; | ||
case('translateY'): | ||
result = this.getTranslateY(animation[0]); | ||
break; | ||
case('scaleX'): | ||
result = this.getScaleX(animation[0]); | ||
break; | ||
case('scaleY'): | ||
result = this.getScaleY(animation[0]); | ||
break; | ||
case('rotate'): | ||
result = this.getRotation(animation[0]); | ||
break; | ||
/* istanbul ignore next */ | ||
default: | ||
result = 0; // TODO: throw an error | ||
} | ||
return result; | ||
} | ||
@@ -61,0 +86,0 @@ }; |
{ | ||
"name": "animar", | ||
"version": "0.2.0", | ||
"description": "A modern, focused, flexible javascript animation library.", | ||
"version": "0.4.0", | ||
"description": "a modern, focused, flexible javascript animation library.", | ||
"keywords": [ | ||
"animation", | ||
"web", | ||
"javascript", | ||
"requestAnimationFrame" | ||
"animation", | ||
"additive" | ||
], | ||
@@ -26,31 +26,38 @@ "author": { | ||
"scripts": { | ||
"test": "gulp test", | ||
"prepublish": "gulp prepublish" | ||
"clean-coverage": "rimraf coverage", | ||
"clean-dist": "rimraf dist", | ||
"clean": "npm run clean-coverage && npm run clean-dist", | ||
"lint": "jshint **.js", | ||
"build": "webpack && webpack --config webpack.config.minified.js", | ||
"deploy": "npm publish ./ && surge --project ./dist --domain animar.surge.sh", | ||
"test": "jest", | ||
"pretest": "npm run clean-coverage && npm run lint", | ||
"prebuild": "npm run clean-dist", | ||
"predeploy": "npm run test && npm run build" | ||
}, | ||
"jshintConfig": {}, | ||
"jest": { | ||
"collectCoverage": true, | ||
"testFileExtensions": [ | ||
"js" | ||
], | ||
"moduleFileExtensions": [ | ||
"js" | ||
], | ||
"testPathDirs": [ | ||
"lib" | ||
] | ||
}, | ||
"directories": { | ||
"lib": "lib" | ||
}, | ||
"main": "dist/animar.js", | ||
"keywords": [ | ||
"web", | ||
"javascript", | ||
"animation", | ||
"additive" | ||
], | ||
"main": "lib/animar.js", | ||
"devDependencies": { | ||
"browserify": "^8.0.2", | ||
"chai": "^1.10.0", | ||
"codeclimate-test-reporter": "0.0.4", | ||
"del": "^1.0.0", | ||
"es6-shim": "^0.22.1", | ||
"gulp": "^3.8.10", | ||
"gulp-istanbul": "^0.5.0", | ||
"gulp-mocha": "^2.0.0", | ||
"gulp-rename": "^1.2.0", | ||
"gulp-uglify": "^1.0.2", | ||
"jsdom": "^2.0.0", | ||
"sinon": "^1.12.1", | ||
"vinyl-buffer": "^1.0.0", | ||
"vinyl-source-stream": "^1.0.0" | ||
"compression-webpack-plugin": "^0.1.2", | ||
"jest-cli": "^0.4.0", | ||
"jshint": "^2.6.0", | ||
"rimraf": "latest", | ||
"webpack": "^1.6.0" | ||
} | ||
} |
@@ -1,2 +0,3 @@ | ||
[![Build Status](https://travis-ci.org/vincentriemer/animar.svg?branch=master)](https://travis-ci.org/vincentriemer/animar) [![Dependency Status](https://david-dm.org/vincentriemer/animar.svg)](https://david-dm.org/vincentriemer/animar) [![devDependency Status](https://david-dm.org/vincentriemer/animar/dev-status.svg)](https://david-dm.org/vincentriemer/animar#info=devDependencies) [![Code Climate](https://codeclimate.com/github/vincentriemer/animar/badges/gpa.svg)](https://codeclimate.com/github/vincentriemer/animar) [![Test Coverage](https://codeclimate.com/github/vincentriemer/animar/badges/coverage.svg)](https://codeclimate.com/github/vincentriemer/animar) | ||
[![Build Status](https://img.shields.io/travis/vincentriemer/animar/master.svg?style=flat)](https://travis-ci.org/vincentriemer/animar) [![Dependency Status](https://img.shields.io/david/vincentriemer/animar.svg?style=flat)](https://david-dm.org/vincentriemer/animar) [![devDependency Status](https://img.shields.io/david/dev/vincentriemer/animar.svg?style=flat)](https://david-dm.org/vincentriemer/animar#info=devDependencies) [![npm version](https://img.shields.io/npm/v/animar.js.svg?style=flat)](http://badge.fury.io/js/animar) [![Code Climate](https://img.shields.io/codeclimate/github/vincentriemer/animar.svg?style=flat)](https://codeclimate.com/github/vincentriemer/animar) [![Test Coverage](https://img.shields.io/codeclimate/coverage/github/vincentriemer/animar.svg?style=flat)](https://codeclimate.com/github/vincentriemer/animar) | ||
# Animar |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
6
2
4
0
48872
17
1166
1