4 function toNumber(value
, allowInfinity
) {
5 return (allowInfinity
&& value
=== 'Infinity') ? Number
.POSITIVE_INFINITY
: Number(value
);
8 Polymer('core-animation',{
10 * Fired when the animation completes.
12 * @event core-animation-finish
17 * Fired when the web animation object changes.
19 * @event core-animation-change
25 * One or more nodes to animate.
28 * @type HTMLElement|Node|Array<HTMLElement|Node>
30 target
: {value
: null, reflect
: true},
33 * Animation keyframes specified as an array of dictionaries of
34 * <css properties>:<array of values> pairs. For example,
39 keyframes
: {value
: null, reflect
: true},
42 * A custom animation function. Either provide this or `keyframes`. The signature
43 * of the callback is `EffectsCallback(timeFraction, target, animation)`
45 * @property customEffect
46 * @type Function(number, Object, Object)
48 customEffect
: {value
: null, reflect
: true},
51 * Controls the composition behavior. If set to "replace", the effect overrides
52 * the underlying value for the target. If set the "add", the effect is added to
53 * the underlying value for the target. If set to "accumulate", the effect is
54 * accumulated to the underlying value for the target.
56 * In cases such as numbers or lengths, "add" and "accumulate" produce the same
57 * value. In list values, "add" is appending to the list, while "accumulate" is
58 * adding the individual components of the list.
60 * For example, adding `translateX(10px)` and `translateX(25px)` produces
61 * `translateX(10px) translateX(25px)` and accumulating produces `translateX(35px)`.
64 * @type "replace"|"add"|"accumulate"
67 composite
: {value
: 'replace', reflect
: true},
70 * Animation duration in milliseconds, "Infinity", or "auto". "auto" is
74 * @type number|"Infinity"
77 duration
: {value
: 'auto', reflect
: true},
80 * Controls the effect the animation has on the target when it's not playing.
81 * The possible values are "none", "forwards", "backwards", "both" or "auto".
83 * "none" means the animation has no effect when it's not playing.
85 * "forward" applies the value at the end of the animation after it's finished.
87 * "backwards" applies the value at the start of the animation to the target
88 * before it starts playing and has no effect when the animation finishes.
90 * "both" means "forwards" and "backwards". "auto" is equivalent to "none".
93 * @type "none"|"forwards"|"backwards"|"both"|"auto"
96 fill
: {value
: 'auto', reflect
: true},
99 * A transition timing function. The values are equivalent to the CSS
106 easing
: {value
: 'linear', reflect
: true},
109 * The number of milliseconds to delay before beginning the animation.
115 delay
: {value
: 0, reflect
: true},
118 * The number of milliseconds to wait after the animation finishes. This is
119 * useful, for example, in an animation group to wait for some time before
120 * beginning the next item in the animation group.
126 endDelay
: {value
: 0, reflect
: true},
129 * The number of iterations this animation should run for.
131 * @property iterations
132 * @type Number|'Infinity'
135 iterations
: {value
: 1, reflect
: true},
138 * Number of iterations into the animation in which to begin the effect.
139 * For example, setting this property to 0.5 and `iterations` to 2 will
140 * cause the animation to begin halfway through the first iteration but still
143 * @property iterationStart
147 iterationStart
: {value
: 0, reflect
: true},
150 * (not working in web animations polyfill---do not use)
152 * Controls the iteration composition behavior. If set to "replace", the effect for
153 * every iteration is independent of each other. If set to "accumulate", the effect
154 * for iterations of the animation will build upon the value in the previous iteration.
158 * // Moves the target 50px on the x-axis over 5 iterations.
159 * <core-animation iterations="5" iterationComposite="accumulate">
160 * <core-animation-keyframe>
161 * <core-animation-prop name="transform" value="translateX(10px)"></core-animation-prop>
162 * </core-animation-keyframe>
165 * @property iterationComposite
166 * @type "replace"|"accumulate"
169 iterationComposite
: {value
: 'replace', reflect
: true},
172 * The playback direction of the animation. "normal" plays the animation in the
173 * normal direction. "reverse" plays it in the reverse direction. "alternate"
174 * alternates the playback direction every iteration such that even iterations are
175 * played normally and odd iterations are reversed. "alternate-reverse" plays
176 * even iterations in the reverse direction and odd iterations in the normal
179 * @property direction
180 * @type "normal"|"reverse"|"alternate"|"alternate-reverse"
183 direction
: {value
: 'normal', reflect
: true},
186 * A multiplier to the playback rate to the animation.
188 * @property playbackRate
192 playbackRate
: {value
: 1, reflect
: true},
195 * If set to true, play the animation when it is created or a property is updated.
201 autoplay
: {value
: false, reflect
: true}
210 customEffect
: 'apply',
216 iterationStart
: 'apply',
217 iterationComposite
: 'apply',
221 playbackRate
: 'apply',
230 * Plays the animation. If the animation is currently paused, seeks the animation
231 * to the beginning before starting playback.
234 * @return AnimationPlayer The animation player.
238 if (this.animation
&& !this.autoplay
) {
239 this.player
= document
.timeline
.play(this.animation
);
240 this.player
.onfinish
= this.animationFinishHandler
.bind(this);
246 * Stops the animation and clears all effects on the target.
252 this.player
.cancel();
257 * Seeks the animation to the end.
263 this.player
.finish();
268 * Pauses the animation.
280 * @return boolean True if `target` is defined.
282 hasTarget: function() {
283 return this.target
!== null;
287 * Creates a web animations object based on this object's properties, and
288 * plays it if autoplay is true.
291 * @return Object A web animation.
294 this.animation
= this.makeAnimation();
295 if (this.autoplay
&& this.animation
) {
298 return this.animation
;
301 makeSingleAnimation: function(target
) {
302 // XXX(yvonne): for selecting all the animated elements.
303 target
.classList
.add('core-animation-target');
304 return new Animation(target
, this.animationEffect
, this.timingProps
);
307 makeAnimation: function() {
312 if (Array
.isArray(this.target
)) {
314 this.target
.forEach(function(t
) {
315 array
.push(this.makeSingleAnimation(t
));
317 animation
= new AnimationGroup(array
);
319 animation
= this.makeSingleAnimation(this.target
);
324 animationChanged: function() {
325 // Sending 'this' with the event so you can always get the animation object
326 // that fired the event, due to event retargetting in shadow DOM.
327 this.fire('core-animation-change', this);
330 targetChanged: function(old
) {
332 old
.classList
.remove('core-animation-target');
339 delay
: {isNumber
: true},
340 endDelay
: {isNumber
: true},
342 iterationStart
: {isNumber
: true},
343 iterations
: {isNumber
: true, allowInfinity
: true},
344 duration
: {isNumber
: true},
345 playbackRate
: {isNumber
: true},
350 if (this[t
] !== null) {
351 var name
= timing
[t
].property
|| t
;
352 props
[name
] = timing
[t
].isNumber
&& this[t
] !== 'auto' ?
353 toNumber(this[t
], timing
[t
].allowInfinity
) : this[t
];
359 get animationEffect() {
363 if (this.keyframes
) {
364 frames
= this.keyframes
;
365 } else if (!this.customEffect
) {
366 var children
= this.querySelectorAll('core-animation-keyframe');
367 if (children
.length
=== 0) {
368 children
= this.shadowRoot
.querySelectorAll('core-animation-keyframe');
370 Array
.prototype.forEach
.call(children
, function(c
) {
371 frames
.push(c
.properties
);
374 if (this.customEffect
) {
375 effect
= this.customEffect
;
377 effect
= new KeyframeEffect(frames
, this.composite
);
382 animationFinishHandler: function() {
383 this.fire('core-animation-finish');
390 Polymer('core-animation-keyframe',{
393 * An offset from 0 to 1.
398 offset
: {value
: null, reflect
: true}
402 var children
= this.querySelectorAll('core-animation-prop');
403 Array
.prototype.forEach
.call(children
, function(c
) {
404 props
[c
.name
] = c
.value
;
406 if (this.offset
!== null) {
407 props
.offset
= this.offset
;
414 Polymer('core-animation-prop',{
417 * A CSS property name.
422 name
: {value
: '', reflect
: true},
425 * The value for the CSS property.
428 * @type string|number
430 value
: {value
: '', reflect
: true}