Skip to content

Commit b9ff3df

Browse files
committed
🍃 Fix bugs with animation library
1 parent 38ae011 commit b9ff3df

File tree

8 files changed

+126
-47
lines changed

8 files changed

+126
-47
lines changed

Ease.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ var Ease = {
3232
linear: function (t) {
3333
return t;
3434
},
35+
36+
// Sine (Sinusoidal)
3537
i1: function (t) {
3638
return -Math.cos(t * (Math.PI / 2)) + 1;
3739
},
@@ -41,6 +43,8 @@ var Ease = {
4143
io1: function (t) {
4244
return -0.5 * (Math.cos(Math.PI * t) - 1);
4345
},
46+
47+
// Quadratic (Quad)
4448
i2: function (t) {
4549
return t * t;
4650
},
@@ -50,6 +54,8 @@ var Ease = {
5054
io2: function (t) {
5155
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
5256
},
57+
58+
// Cubic
5359
i3: function (t) {
5460
return t * t * t;
5561
},
@@ -59,6 +65,8 @@ var Ease = {
5965
io3: function (t) {
6066
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
6167
},
68+
69+
// Quartic (Quart)
6270
i4: function (t) {
6371
return t * t * t * t;
6472
},
@@ -68,6 +76,8 @@ var Ease = {
6876
io4: function (t) {
6977
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
7078
},
79+
80+
// Quintic (Quint)
7181
i5: function (t) {
7282
return t * t * t * t * t;
7383
},
@@ -77,11 +87,15 @@ var Ease = {
7787
io5: function (t) {
7888
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t;
7989
},
90+
91+
// Exponential (Expo)
8092
i6: function (t) {
8193
return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1));
8294
},
8395
o6: function (t) {
84-
return (t === 1) ? 1 : 1 - Math.pow(2, -10 * t);
96+
var OUT_EXPO_CORRECTION = 1.000976;
97+
return (t === 1) ? 1 : 1 * OUT_EXPO_CORRECTION * (-Math.pow(2, -10 * t) + 1);
98+
// return (t === 1) ? 1 : 1 - Math.pow(2, -10 * t);
8599
},
86100
io6: function (t) {
87101
if (t === 0) return 0;

animate.js

Lines changed: 104 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import clamp from './clamp';
22
import Ease from './Ease';
3+
import forEachIn from './forEachIn';
34
import lerp from './lerp';
45
import round from './round';
56

@@ -208,34 +209,34 @@ function parseProperties(p) {
208209
var properties = clone(p);
209210

210211
// Transform some properties if needed.
211-
if (properties.scale) {
212+
if (typeof properties.scale !== "undefined") {
212213
properties.scaleX = properties.scale;
213214
properties.scaleY = properties.scale;
214215
delete properties.scale;
215216
}
216217

217-
if (properties.rotate) {
218+
if (typeof properties.rotate !== "undefined") {
218219
properties.rotateX = properties.rotate;
219220
properties.rotateY = properties.rotate;
220221
delete properties.rotate;
221222
}
222223

223-
if (properties.x) {
224+
if (typeof properties.x !== "undefined") {
224225
properties.translateX = properties.x;
225226
delete properties.x;
226227
}
227228

228-
if (properties.y) {
229-
properties.translateX = properties.x;
229+
if (typeof properties.y !== "undefined") {
230+
properties.translateY = properties.y;
230231
delete properties.y;
231232
}
232233

233-
if (properties.z) {
234+
if (typeof properties.z !== "undefined") {
234235
properties.translateZ = properties.z;
235236
delete properties.z;
236237
}
237238

238-
Object.keys(properties).forEach(function(key){
239+
forEachIn(Object.keys(properties))(function(key){
239240
var property = properties[key];
240241
var isPropertyArray = Array.isArray(property);
241242
var parsedStringProperty = parseStringProperty(property);
@@ -272,33 +273,68 @@ function parseProperties(p) {
272273
return properties;
273274
}
274275

276+
/**
277+
* Return a translation array from a
278+
* string (retrieved from style for example)
279+
* @param {String} transformationString
280+
* @returns {[x: String, y: String, z: String]}
281+
*/
282+
function getTranslationArrayFromString(transformationString) {
283+
var translationArray = ["0", "0", "0"];
284+
285+
if (transformationString.indexOf('translate3d') !== -1) {
286+
var translation = transformationString.match(/translate3d\(([^)]+),([^)]+),([^)]+)\)/);
287+
translationArray[0] = translation[1].trim();
288+
translationArray[1] = translation[2].trim();
289+
translationArray[2] = translation[3].trim();
290+
}
291+
292+
return translationArray;
293+
}
294+
275295
/**
276296
* Returns the transform value of an element.
297+
* TODO: Convert units when reading values.
277298
* @param {HTMLElement|Object} element The animatable element.
278299
* @param {String} propertyKey The key name of the property to animate.
279300
* @returns {Number}
280301
*/
281302
function getElementTransformValue(element, propertyKey) {
282-
283-
// Typically here I've to try reading
303+
// Typically we've to try reading
284304
// the value from the style attribute first,
285-
// if there is no value there, I can call the getComputedStyle then :'(
305+
// if there is no value there, We should call the getComputedStyle then :'(
286306
var transformationStyleString = element.style.transform;
287-
if (!transformationStyleString) {
288-
// It seems like getComputedStyle returns
289-
// either the string "none"
307+
if (typeof transformationStyleString === "string" && transformationStyleString.length > 0) {
308+
// We're reading value from element style attribute.
309+
// If we found the property inside the string, we get value.
310+
311+
// If it is a translation, we'll
312+
// retrieve the value from translate3d prop.
313+
if (arrayContains(["translateX", "translateY", "translateZ"], propertyKey)) {
314+
if (transformationStyleString.indexOf('translate3d') !== -1) {
315+
var translationArray = getTranslationArrayFromString(transformationStyleString);
316+
switch (propertyKey) {
317+
case "translateX": return parseFloat(translationArray[0]);
318+
case "translateY": return parseFloat(translationArray[1]);
319+
case "translateZ": return parseFloat(translationArray[2]);
320+
default: break;
321+
}
322+
}
323+
}
324+
else {
325+
var values = transformationStyleString.match(new RegExp(propertyKey + "\(([^)]+)\)"));
326+
return Array.isArray(values) && values[1]
327+
? parseStringProperty(values[1].substr(1))[0]
328+
: arrayContains(["scale", "scaleX", "scaleY"], propertyKey) ? 1 : 0;
329+
}
330+
}
331+
332+
else {
333+
// Let's call getComputedStyle.
334+
// the function returns either the string "none"
290335
// or the computed transformation in the form of a matrix.
291336
//var computedTransformValue = getComputedStyle(element).getPropertyValue("transform");
292337
if (arrayContains(["scale", "scaleX", "scaleY"], propertyKey)) return 1;
293-
} else {
294-
// We're reading value from element style attribute.
295-
// If we found the property inside the string, we get value.
296-
// EDIT: (Ignore) Else, we try to look for the group property and we remove the value there.
297-
// Else, we're definitely sure that the value is not set and we return 0.
298-
var values = transformationStyleString.match(new RegExp(propertyKey + "\(([^)]+)\)"));
299-
return Array.isArray(values) && values[1]
300-
? parseStringProperty(values[1].substr(1))[0]
301-
: arrayContains(["scale", "scaleX", "scaleY"], propertyKey) ? 1 : 0;
302338
}
303339

304340
return 0;
@@ -320,6 +356,23 @@ function getElementPropertyValue(element, animationType, propertyKey) {
320356
}
321357
}
322358

359+
/**
360+
* Apply a translation to the element.
361+
* @param {HTMLElement} element
362+
* @param {String} transformationString
363+
* @param {Array} translationArray
364+
*/
365+
function applyTheTranslationArray(element, transformationString, translationArray) {
366+
var regex = /translate3d\(([^)]+)\)/;
367+
var translationString = "translate3d("+translationArray[0]+","+translationArray[1]+","+translationArray[2]+")";
368+
369+
element.style.transform =
370+
transformationString.indexOf('translate3d') !== -1
371+
? transformationString.replace(regex, translationString)
372+
: transformationString + " " + translationString
373+
;
374+
}
375+
323376
/**
324377
* Set a value to the transformation property.
325378
* @param {HTMLElement|Object} element The animatable element.
@@ -332,11 +385,30 @@ function setElementTransformValue(element, propertyKey, value) {
332385
// If the current transformation property key already exist in the string, we just have to replace its value.
333386
// Else we create a new string and we add it in the transformation string.
334387
var transformationString = element.style.transform;
335-
element.style.transform =
336-
transformationString.indexOf(propertyKey) !== -1
337-
? transformationString.replace(new RegExp(propertyKey + "\(([^)]+)\)"), propertyKey + "("+value)
338-
: transformationString + " " + propertyKey + "("+value+")"
339-
;
388+
389+
// If we tryng to do a translation, use translate3d rather.
390+
if (arrayContains(["translateX", "translateY", "translateZ"], propertyKey)) {
391+
// Generate the translation array from the transformation string.
392+
var translationArray = getTranslationArrayFromString(transformationString);
393+
// Fill out the array with the current values.
394+
switch (propertyKey) {
395+
case "translateX": translationArray[0] = value; break;
396+
case "translateY": translationArray[1] = value; break;
397+
case "translateZ": translationArray[2] = value; break;
398+
default: break;
399+
}
400+
// Apply the translation.
401+
applyTheTranslationArray(element, transformationString, translationArray);
402+
}
403+
404+
// We're trying to do other transformation than translation.
405+
else {
406+
element.style.transform =
407+
transformationString.indexOf(propertyKey) !== -1
408+
? transformationString.replace(new RegExp(propertyKey + "\(([^)]+)\)"), propertyKey + "("+value)
409+
: transformationString + " " + propertyKey + "("+value+")"
410+
;
411+
}
340412
}
341413

342414
/**
@@ -473,7 +545,7 @@ function generateAnimations(elements, params) {
473545
var properties = parseProperties(params.p);
474546
var animations = [];
475547
var instanceDuration = 0;
476-
elements.forEach(function(element, index) {
548+
forEachIn(elements)(function(element, index) {
477549
// For each property of each element,
478550
// we create an animation.
479551
// EDIT: For more control, I need to group transformation animations into one animation.
@@ -486,7 +558,7 @@ function generateAnimations(elements, params) {
486558
animationTotalDuration > instanceDuration
487559
? animationTotalDuration
488560
: instanceDuration;
489-
Object.keys(properties).forEach(function (key) {
561+
forEachIn(Object.keys(properties))(function(key) {
490562
var property = { n: key, v: properties[key] };
491563
// Get the animation type.
492564
var animationType = getAnimationType(key);
@@ -647,12 +719,7 @@ function animate(params) {
647719
* @param {Number} time The instance time.
648720
*/
649721
function setAnimationsProgress(time) {
650-
var i = 0;
651-
var animations = instance.a;
652-
var animationsLength = animations.length;
653-
while(i < animationsLength) {
654-
/** @type {AnimationInstance} */
655-
var animation = animations[i];
722+
forEachIn(instance.a)(function(animation) {
656723
var delay = animation.v.D;
657724
var duration = animation.v.d;
658725
var easing = animation.v.e;
@@ -678,12 +745,11 @@ function animate(params) {
678745
);
679746
var startValue = animation.p.v.s;
680747
var endValue = animation.p.v.e;
681-
animation.p.v.c = round(lerp(startValue, endValue, eased), 4);
748+
animation.p.v.c = round(lerp(startValue, endValue, eased), 3);
682749
// Set animation value.
683750
setElementValue(animation.el, animation.type, animation.p.n, animation.p.v.c, animation.p.v.u);
684751
}
685-
i++;
686-
}
752+
});
687753
}
688754

689755
/**

0 commit comments

Comments
 (0)