Skip to content

Commit b4443d3

Browse files
committed
Merge remote-tracking branch 'origin/master' into HEAD
2 parents 7215de4 + af340d4 commit b4443d3

11 files changed

+561
-82
lines changed

History.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
### 2.1.1 - *July 1 2015*
2+
* Add Animation.timeline getter
3+
* Add AnimationEffect.parent getter
4+
* Make AnimationEffectTiming (returned by AnimationEffect.timing) attributes mutable
5+
* Expose the Animation constructor
6+
* Change custom effects from AnimationEffects to onsample functions. Custom effects should now be created by setting the onsample attribute of a KeyframeEffect.
7+
8+
For example, this is deprecated:
9+
10+
var myEffect = new KeyframeEffect(
11+
element,
12+
function(timeFraction, target, effect) {
13+
target.style.opacity = timeFraction;
14+
},
15+
1000);
16+
var myAnimation = document.timeline.play(myEffect);
17+
18+
and this should be used insead:
19+
20+
var myEffect = new KeyframeEffect(element, [], 1000);
21+
effect.onsample = function(timeFraction, effect, animation) {
22+
effect.target.style.opacity = timeFraction;
23+
};
24+
var myAnimation = document.timeline.play(myEffect);
25+
126
### 2.1.0 - *June 15 2015*
227
* Fix bug affecting GroupEffects with infinite iteration children
328
* Add GroupEffect.firstChild and GroupEffect.lastChild

src/effect-callback.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@
1818
var sequenceNumber = 0;
1919
scope.bindAnimationForCustomEffect = function(animation) {
2020
var target = animation.effect.target;
21-
var effectFunction = animation.effect._normalizedKeyframes;
21+
var effectFunction;
22+
var isKeyframeEffect = typeof animation.effect.getFrames() == 'function';
23+
if (isKeyframeEffect) {
24+
effectFunction = animation.effect.getFrames();
25+
} else {
26+
effectFunction = animation.effect._onsample;
27+
}
2228
var timing = animation.effect.timing;
2329
var last = null;
2430
timing = shared.normalizeTimingInput(timing);
@@ -31,8 +37,13 @@
3137
}
3238
// FIXME: There are actually more conditions under which the effectFunction
3339
// should be called.
34-
if (t !== last)
35-
effectFunction(t, target, animation.effect);
40+
if (t !== last) {
41+
if (isKeyframeEffect) {
42+
effectFunction(t, target, animation.effect);
43+
} else {
44+
effectFunction(t, animation.effect, animation.effect._animation);
45+
}
46+
}
3647
last = t;
3748
};
3849

src/group-constructors.js

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
this._parent = null;
2323
this.children = children || [];
2424
this._reparent(this.children);
25+
timingInput = shared.numericTimingToObject(timingInput);
2526
this._timingInput = shared.cloneTimingInput(timingInput);
2627
this._timing = shared.normalizeTimingInput(timingInput, true);
27-
this.timing = shared.makeTiming(timingInput, true);
28+
this.timing = shared.makeTiming(timingInput, true, this);
29+
this.timing._effect = this;
2830

2931
if (this._timing.duration === 'auto') {
3032
this._timing.duration = this.activeDuration;
@@ -92,6 +94,9 @@
9294
prepend: function() {
9395
this._putChild(arguments, false);
9496
},
97+
get parent() {
98+
return this._parent;
99+
},
95100
get firstChild() {
96101
return this.children.length ? this.children[0] : null;
97102
},
@@ -179,7 +184,9 @@
179184
}
180185
};
181186

182-
underlyingAnimation = scope.timeline._play(new scope.KeyframeEffect(null, ticker, group._timing));
187+
var underlyingEffect = new KeyframeEffect(null, [], group._timing);
188+
underlyingEffect.onsample = ticker;
189+
underlyingAnimation = scope.timeline._play(underlyingEffect);
183190
return underlyingAnimation;
184191
};
185192

@@ -193,21 +200,4 @@
193200

194201
scope.groupChildDuration = groupChildDuration;
195202

196-
// Alias GroupEffect & SequenceEffect to AnimationGroup & AnimationSequence respectively, to
197-
// support old constructors (Animation*) for a deprecation period. Should be removed after 23 June
198-
// 2015.
199-
window.AnimationSequence = function() {
200-
shared.deprecated('window.AnimationSequence', '2015-03-23', 'Use window.SequenceEffect instead.');
201-
window.SequenceEffect.apply(this, arguments);
202-
};
203-
window.AnimationSequence.prototype = Object.create(window.SequenceEffect.prototype);
204-
window.AnimationSequence.prototype.constructor = window.AnimationSequence;
205-
206-
window.AnimationGroup = function() {
207-
shared.deprecated('window.AnimationGroup', '2015-03-23', 'Use window.GroupEffect instead.');
208-
window.GroupEffect.apply(this, arguments);
209-
};
210-
window.AnimationGroup.prototype = Object.create(window.GroupEffect.prototype);
211-
window.AnimationGroup.prototype.constructor = window.AnimationGroup;
212-
213203
})(webAnimationsShared, webAnimationsNext, webAnimationsTesting);

src/keyframe-effect-constructor.js

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,20 @@
5555

5656
scope.KeyframeEffect = function(target, effectInput, timingInput) {
5757
this.target = target;
58+
this._parent = null;
5859

60+
timingInput = shared.numericTimingToObject(timingInput);
5961
this._timingInput = shared.cloneTimingInput(timingInput);
6062
this._timing = shared.normalizeTimingInput(timingInput);
6163

62-
this.timing = shared.makeTiming(timingInput);
63-
if (typeof effectInput == 'function')
64+
this.timing = shared.makeTiming(timingInput, false, this);
65+
this.timing._effect = this;
66+
if (typeof effectInput == 'function') {
67+
shared.deprecated('Custom KeyframeEffect', '2015-06-22', 'Use KeyframeEffect.onsample instead.');
6468
this._normalizedKeyframes = effectInput;
65-
else
69+
} else {
6670
this._normalizedKeyframes = new KeyframeList(effectInput);
71+
}
6772
this._keyframes = effectInput;
6873
this.activeDuration = shared.calculateActiveDuration(this._timing);
6974
return this;
@@ -75,9 +80,17 @@
7580
return this._normalizedKeyframes;
7681
return this._normalizedKeyframes._frames;
7782
},
78-
get effect() {
79-
shared.deprecated('KeyframeEffect.effect', '2015-03-23', 'Use KeyframeEffect.getFrames() instead.');
80-
return this._normalizedKeyframes;
83+
set onsample(callback) {
84+
if (typeof this.getFrames() == 'function') {
85+
throw new Error('Setting onsample on custom effect KeyframeEffect is not supported.');
86+
}
87+
this._onsample = callback;
88+
if (this._animation) {
89+
this._animation._rebuildUnderlyingAnimation();
90+
}
91+
},
92+
get parent() {
93+
return this._parent;
8194
},
8295
clone: function() {
8396
if (typeof this.getFrames() == 'function') {
@@ -115,6 +128,7 @@
115128
return originalElementAnimate.apply(target, [keyframes, timing]);
116129
};
117130

131+
// TODO: Remove this once we remove support for custom KeyframeEffects.
118132
scope.bindAnimationForKeyframeEffect = function(animation) {
119133
if (animation.effect && typeof animation.effect._normalizedKeyframes == 'function') {
120134
scope.bindAnimationForCustomEffect(animation);
@@ -159,25 +173,5 @@
159173
return animation.effect !== null && animation.effect.target == this;
160174
}.bind(this));
161175
};
162-
window.Element.prototype.getAnimationPlayers = function() {
163-
shared.deprecated('Element.getAnimationPlayers', '2015-03-23', 'Use Element.getAnimations instead.');
164-
return this.getAnimations();
165-
};
166-
167-
// Alias KeyframeEffect to Animation, to support old constructor (Animation) for a deprecation
168-
// period. Should be removed after 23 June 2015.
169-
//
170-
// This is only on window and not on scope, because the constructor that was called
171-
// webAnimationsNext.Player - now called webAnimationsNext.Animation - is already on the scope.
172-
//
173-
// FIXME: Add this to scope & expose the other scope.Animation (nee scope.Player). I.e. both this
174-
// function and the constructor in web-animations-next-animation should be scope.Animation and
175-
// window.Animation until 23 June 2015.
176-
window.Animation = function() {
177-
shared.deprecated('window.Animation', '2015-03-23', 'Use window.KeyframeEffect instead.');
178-
window.KeyframeEffect.apply(this, arguments);
179-
};
180-
window.Animation.prototype = Object.create(window.KeyframeEffect.prototype);
181-
window.Animation.prototype.constructor = window.Animation;
182176

183177
}(webAnimationsShared, webAnimationsNext, webAnimationsTesting));

src/timeline.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@
3333
this._discardAnimations();
3434
return this._animations.slice();
3535
},
36-
getAnimationPlayers: function() {
37-
shared.deprecated('AnimationTimeline.getAnimationPlayers', '2015-03-23', 'Use AnimationTimeline.getAnimations instead.');
38-
return this.getAnimations();
39-
},
4036
_updateAnimationsPromises: function() {
4137
scope.animationsWithPromises = scope.animationsWithPromises.filter(function(animation) {
4238
return animation._updatePromises();
@@ -49,7 +45,7 @@
4945
});
5046
},
5147
_play: function(effect) {
52-
var animation = new scope.Animation(effect);
48+
var animation = new scope.Animation(effect, this);
5349
this._animations.push(animation);
5450
scope.restartWebAnimationsNextTick();
5551
// Use animation._animation.play() here, NOT animation.play().

src/timing-utilities.js

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,53 @@
2828
return clone;
2929
}
3030

31-
function makeTiming(timingInput, forGroup) {
32-
var timing = {
33-
delay: 0,
34-
endDelay: 0,
35-
fill: forGroup ? 'both' : 'none',
36-
iterationStart: 0,
37-
iterations: 1,
38-
duration: forGroup ? 'auto' : 0,
39-
playbackRate: 1,
40-
direction: 'normal',
41-
easing: 'linear',
42-
};
31+
function AnimationEffectTiming() {
32+
this._delay = 0;
33+
this._endDelay = 0;
34+
this._fill = 'none';
35+
this._iterationStart = 0;
36+
this._iterations = 1;
37+
this._duration = 0;
38+
this._playbackRate = 1;
39+
this._direction = 'normal';
40+
this._easing = 'linear';
41+
}
42+
43+
AnimationEffectTiming.prototype = {
44+
_setMember: function(member, value) {
45+
this['_' + member] = value;
46+
if (this._effect) {
47+
this._effect._timingInput[member] = value;
48+
this._effect._timing = shared.normalizeTimingInput(shared.normalizeTimingInput(this._effect._timingInput));
49+
this._effect.activeDuration = shared.calculateActiveDuration(this._effect._timing);
50+
if (this._effect._animation) {
51+
this._effect._animation._rebuildUnderlyingAnimation();
52+
}
53+
}
54+
},
55+
get playbackRate() {
56+
return this._playbackRate;
57+
},
58+
};
59+
60+
var members = ['delay', 'endDelay', 'fill', 'iterationStart',
61+
'duration', 'direction', 'easing', 'iterations'];
62+
members.forEach(function(name) {
63+
Object.defineProperty(
64+
AnimationEffectTiming.prototype,
65+
name,
66+
{
67+
get: function() { return this['_' + name]; },
68+
set: function(value) { this._setMember(name, value); }
69+
});
70+
});
71+
72+
function makeTiming(timingInput, forGroup, effect) {
73+
var timing = new AnimationEffectTiming();
74+
if (forGroup) {
75+
timing.fill = 'both';
76+
timing.duration = 'auto';
77+
}
4378
if (typeof timingInput == 'number' && !isNaN(timingInput)) {
4479
timing.duration = timingInput;
4580
} else if (timingInput !== undefined) {
@@ -66,9 +101,21 @@
66101
return timing;
67102
}
68103

104+
function numericTimingToObject(timingInput) {
105+
if (typeof timingInput == 'number') {
106+
if (isNaN(timingInput)) {
107+
timingInput = { duration: 0 };
108+
} else {
109+
timingInput = { duration: timingInput };
110+
}
111+
}
112+
return timingInput;
113+
}
114+
69115
function normalizeTimingInput(timingInput, forGroup) {
116+
timingInput = shared.numericTimingToObject(timingInput);
70117
var timing = makeTiming(timingInput, forGroup);
71-
timing.easing = toTimingFunction(timing.easing);
118+
timing._easing = toTimingFunction(timing.easing);
72119
return timing;
73120
}
74121

@@ -232,6 +279,7 @@
232279

233280
shared.cloneTimingInput = cloneTimingInput;
234281
shared.makeTiming = makeTiming;
282+
shared.numericTimingToObject = numericTimingToObject;
235283
shared.normalizeTimingInput = normalizeTimingInput;
236284
shared.calculateActiveDuration = calculateActiveDuration;
237285
shared.calculateTimeFraction = calculateTimeFraction;

src/web-animations-next-animation.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@
1515
(function(shared, scope, testing) {
1616
scope.animationsWithPromises = [];
1717

18-
scope.Animation = function(effect) {
18+
scope.Animation = function(effect, timeline) {
1919
this.effect = effect;
2020
if (effect) {
2121
effect._animation = this;
2222
}
23+
if (!timeline) {
24+
throw new Error('Animation with null timeline is not supported');
25+
}
26+
this._timeline = timeline;
2327
this._sequenceNumber = shared.sequenceNumber++;
2428
this._holdTime = 0;
2529
this._paused = false;
@@ -86,6 +90,9 @@
8690
this._animation = scope.newUnderlyingAnimationForGroup(this.effect);
8791
scope.bindAnimationForGroup(this);
8892
}
93+
if (this.effect && this.effect._onsample) {
94+
scope.bindAnimationForCustomEffect(this);
95+
}
8996
if (hadUnderlying) {
9097
if (oldPlaybackRate != 1) {
9198
this.playbackRate = oldPlaybackRate;
@@ -148,6 +155,9 @@
148155
childAnimation.startTime = this.startTime + offset / this.playbackRate;
149156
}
150157
},
158+
get timeline() {
159+
return this._timeline;
160+
},
151161
get playState() {
152162
return this._animation ? this._animation.playState : 'idle';
153163
},
@@ -259,16 +269,12 @@
259269
}
260270
this._updatePromises();
261271
},
262-
get source() {
263-
shared.deprecated('Animation.source', '2015-03-23', 'Use Animation.effect instead.');
264-
return this.effect;
265-
},
266272
play: function() {
267273
this._updatePromises();
268274
this._paused = false;
269275
this._animation.play();
270-
if (document.timeline._animations.indexOf(this) == -1) {
271-
document.timeline._animations.push(this);
276+
if (this._timeline._animations.indexOf(this) == -1) {
277+
this._timeline._animations.push(this);
272278
}
273279
this._register();
274280
scope.awaitStartTime(this);
@@ -356,7 +362,10 @@
356362
},
357363
};
358364

365+
window.Animation = scope.Animation;
366+
359367
if (WEB_ANIMATIONS_TESTING) {
360368
testing.webAnimationsNextAnimation = scope.Animation;
361369
}
370+
362371
})(webAnimationsShared, webAnimationsNext, webAnimationsTesting);

0 commit comments

Comments
 (0)