| OLD | NEW |
| (Empty) |
| 1 | |
| 2 (function() { | |
| 3 | |
| 4 function toNumber(value, allowInfinity) { | |
| 5 return (allowInfinity && value === 'Infinity') ? Number.POSITIVE_INFINIT
Y : Number(value); | |
| 6 }; | |
| 7 | |
| 8 Polymer('core-animation',{ | |
| 9 /** | |
| 10 * Fired when the animation completes. | |
| 11 * | |
| 12 * @event core-animation-finish | |
| 13 */ | |
| 14 | |
| 15 /** | |
| 16 * | |
| 17 * Fired when the web animation object changes. | |
| 18 * | |
| 19 * @event core-animation-change | |
| 20 */ | |
| 21 | |
| 22 publish: { | |
| 23 | |
| 24 /** | |
| 25 * One or more nodes to animate. | |
| 26 * | |
| 27 * @property target | |
| 28 * @type HTMLElement|Node|Array<HTMLElement|Node> | |
| 29 */ | |
| 30 target: {value: null, reflect: true}, | |
| 31 | |
| 32 /** | |
| 33 * Animation keyframes specified as an array of dictionaries of | |
| 34 * <css properties>:<array of values> pairs. For example, | |
| 35 * | |
| 36 * @property keyframes | |
| 37 * @type Object | |
| 38 */ | |
| 39 keyframes: {value: null, reflect: true}, | |
| 40 | |
| 41 /** | |
| 42 * A custom animation function. Either provide this or `keyframes`. Th
e signature | |
| 43 * of the callback is `EffectsCallback(timeFraction, target, animation
)` | |
| 44 * | |
| 45 * @property customEffect | |
| 46 * @type Function(number, Object, Object) | |
| 47 */ | |
| 48 customEffect: {value: null, reflect: true}, | |
| 49 | |
| 50 /** | |
| 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 i
s added to | |
| 53 * the underlying value for the target. If set to "accumulate", the ef
fect is | |
| 54 * accumulated to the underlying value for the target. | |
| 55 * | |
| 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 "accum
ulate" is | |
| 58 * adding the individual components of the list. | |
| 59 * | |
| 60 * For example, adding `translateX(10px)` and `translateX(25px)` produ
ces | |
| 61 * `translateX(10px) translateX(25px)` and accumulating produces `tran
slateX(35px)`. | |
| 62 * | |
| 63 * @property composite | |
| 64 * @type "replace"|"add"|"accumulate" | |
| 65 * @default "replace" | |
| 66 */ | |
| 67 composite: {value: 'replace', reflect: true}, | |
| 68 | |
| 69 /** | |
| 70 * Animation duration in milliseconds, "Infinity", or "auto". "auto" i
s | |
| 71 * equivalent to 0. | |
| 72 * | |
| 73 * @property duration | |
| 74 * @type number|"Infinity" | |
| 75 * @default "auto" | |
| 76 */ | |
| 77 duration: {value: 'auto', reflect: true}, | |
| 78 | |
| 79 /** | |
| 80 * Controls the effect the animation has on the target when it's not p
laying. | |
| 81 * The possible values are "none", "forwards", "backwards", "both" or
"auto". | |
| 82 * | |
| 83 * "none" means the animation has no effect when it's not playing. | |
| 84 * | |
| 85 * "forwards" applies the value at the end of the animation after it's
finished. | |
| 86 * | |
| 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 finis
hes. | |
| 89 * | |
| 90 * "both" means "forwards" and "backwards". "auto" is equivalent to "n
one". | |
| 91 * | |
| 92 * @property fill | |
| 93 * @type "none"|"forwards"|"backwards"|"both"|"auto" | |
| 94 * @default "auto" | |
| 95 */ | |
| 96 fill: {value: 'auto', reflect: true}, | |
| 97 | |
| 98 /** | |
| 99 * A transition timing function. The values are equivalent to the CSS | |
| 100 * counterparts. | |
| 101 * | |
| 102 * @property easing | |
| 103 * @type string | |
| 104 * @default "linear" | |
| 105 */ | |
| 106 easing: {value: 'linear', reflect: true}, | |
| 107 | |
| 108 /** | |
| 109 * The number of milliseconds to delay before beginning the animation. | |
| 110 * | |
| 111 * @property delay | |
| 112 * @type Number | |
| 113 * @default 0 | |
| 114 */ | |
| 115 delay: {value: 0, reflect: true}, | |
| 116 | |
| 117 /** | |
| 118 * The number of milliseconds to wait after the animation finishes. Th
is is | |
| 119 * useful, for example, in an animation group to wait for some time be
fore | |
| 120 * beginning the next item in the animation group. | |
| 121 * | |
| 122 * @property endDelay | |
| 123 * @type number | |
| 124 * @default 0 | |
| 125 */ | |
| 126 endDelay: {value: 0, reflect: true}, | |
| 127 | |
| 128 /** | |
| 129 * The number of iterations this animation should run for. | |
| 130 * | |
| 131 * @property iterations | |
| 132 * @type Number|'Infinity' | |
| 133 * @default 1 | |
| 134 */ | |
| 135 iterations: {value: 1, reflect: true}, | |
| 136 | |
| 137 /** | |
| 138 * Number of iterations into the animation in which to begin the effec
t. | |
| 139 * For example, setting this property to 0.5 and `iterations` to 2 wil
l | |
| 140 * cause the animation to begin halfway through the first iteration bu
t still | |
| 141 * run twice. | |
| 142 * | |
| 143 * @property iterationStart | |
| 144 * @type Number | |
| 145 * @default 0 | |
| 146 */ | |
| 147 iterationStart: {value: 0, reflect: true}, | |
| 148 | |
| 149 /** | |
| 150 * (not working in web animations polyfill---do not use) | |
| 151 * | |
| 152 * Controls the iteration composition behavior. If set to "replace", t
he 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 pr
evious iteration. | |
| 155 * | |
| 156 * Example: | |
| 157 * | |
| 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> | |
| 163 * </core-animation> | |
| 164 * | |
| 165 * @property iterationComposite | |
| 166 * @type "replace"|"accumulate" | |
| 167 * @default false | |
| 168 */ | |
| 169 iterationComposite: {value: 'replace', reflect: true}, | |
| 170 | |
| 171 /** | |
| 172 * The playback direction of the animation. "normal" plays the animati
on in the | |
| 173 * normal direction. "reverse" plays it in the reverse direction. "alt
ernate" | |
| 174 * alternates the playback direction every iteration such that even it
erations 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 | |
| 177 * direction. | |
| 178 * | |
| 179 * @property direction | |
| 180 * @type "normal"|"reverse"|"alternate"|"alternate-reverse" | |
| 181 * @default "normal" | |
| 182 */ | |
| 183 direction: {value: 'normal', reflect: true}, | |
| 184 | |
| 185 /** | |
| 186 * A multiplier to the playback rate to the animation. | |
| 187 * | |
| 188 * @property playbackRate | |
| 189 * @type number | |
| 190 * @default 1 | |
| 191 */ | |
| 192 playbackRate: {value: 1, reflect: true}, | |
| 193 | |
| 194 /** | |
| 195 * If set to true, play the animation when it is created or a property
is updated. | |
| 196 * | |
| 197 * @property autoplay | |
| 198 * @type boolean | |
| 199 * @default false | |
| 200 */ | |
| 201 autoplay: {value: false, reflect: true} | |
| 202 | |
| 203 }, | |
| 204 | |
| 205 animation: false, | |
| 206 | |
| 207 observe: { | |
| 208 target: 'apply', | |
| 209 keyframes: 'apply', | |
| 210 customEffect: 'apply', | |
| 211 composite: 'apply', | |
| 212 duration: 'apply', | |
| 213 fill: 'apply', | |
| 214 easing: 'apply', | |
| 215 iterations: 'apply', | |
| 216 iterationStart: 'apply', | |
| 217 iterationComposite: 'apply', | |
| 218 delay: 'apply', | |
| 219 endDelay: 'apply', | |
| 220 direction: 'apply', | |
| 221 playbackRate: 'apply', | |
| 222 autoplay: 'apply' | |
| 223 }, | |
| 224 | |
| 225 ready: function() { | |
| 226 this.apply(); | |
| 227 }, | |
| 228 | |
| 229 /** | |
| 230 * Plays the animation. If the animation is currently paused, seeks the
animation | |
| 231 * to the beginning before starting playback. | |
| 232 * | |
| 233 * @method play | |
| 234 * @return AnimationPlayer The animation player. | |
| 235 */ | |
| 236 play: function() { | |
| 237 this.apply(); | |
| 238 if (this.animation && !this.autoplay) { | |
| 239 this.player = document.timeline.play(this.animation); | |
| 240 this.player.onfinish = this.animationFinishHandler.bind(this); | |
| 241 return this.player; | |
| 242 } | |
| 243 }, | |
| 244 | |
| 245 /** | |
| 246 * Stops the animation and clears all effects on the target. | |
| 247 * | |
| 248 * @method cancel | |
| 249 */ | |
| 250 cancel: function() { | |
| 251 if (this.player) { | |
| 252 this.player.cancel(); | |
| 253 } | |
| 254 }, | |
| 255 | |
| 256 /** | |
| 257 * Seeks the animation to the end. | |
| 258 * | |
| 259 * @method finish | |
| 260 */ | |
| 261 finish: function() { | |
| 262 if (this.player) { | |
| 263 this.player.finish(); | |
| 264 } | |
| 265 }, | |
| 266 | |
| 267 /** | |
| 268 * Pauses the animation. | |
| 269 * | |
| 270 * @method pause | |
| 271 */ | |
| 272 pause: function() { | |
| 273 if (this.player) { | |
| 274 this.player.pause(); | |
| 275 } | |
| 276 }, | |
| 277 | |
| 278 /** | |
| 279 * @method hasTarget | |
| 280 * @return boolean True if `target` is defined. | |
| 281 */ | |
| 282 hasTarget: function() { | |
| 283 return this.target !== null; | |
| 284 }, | |
| 285 | |
| 286 /** | |
| 287 * Creates a web animations object based on this object's properties, an
d | |
| 288 * plays it if autoplay is true. | |
| 289 * | |
| 290 * @method apply | |
| 291 * @return Object A web animation. | |
| 292 */ | |
| 293 apply: function() { | |
| 294 this.animation = this.makeAnimation(); | |
| 295 if (this.autoplay && this.animation) { | |
| 296 this.play(); | |
| 297 } | |
| 298 return this.animation; | |
| 299 }, | |
| 300 | |
| 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); | |
| 305 }, | |
| 306 | |
| 307 makeAnimation: function() { | |
| 308 if (!this.target) { | |
| 309 return null; | |
| 310 } | |
| 311 var animation; | |
| 312 if (Array.isArray(this.target)) { | |
| 313 var array = []; | |
| 314 this.target.forEach(function(t) { | |
| 315 array.push(this.makeSingleAnimation(t)); | |
| 316 }.bind(this)); | |
| 317 animation = new AnimationGroup(array); | |
| 318 } else { | |
| 319 animation = this.makeSingleAnimation(this.target); | |
| 320 } | |
| 321 return animation; | |
| 322 }, | |
| 323 | |
| 324 animationChanged: function() { | |
| 325 // Sending 'this' with the event so you can always get the animation o
bject | |
| 326 // that fired the event, due to event retargetting in shadow DOM. | |
| 327 this.fire('core-animation-change', this); | |
| 328 }, | |
| 329 | |
| 330 targetChanged: function(old) { | |
| 331 if (old) { | |
| 332 old.classList.remove('core-animation-target'); | |
| 333 } | |
| 334 }, | |
| 335 | |
| 336 get timingProps() { | |
| 337 var props = {}; | |
| 338 var timing = { | |
| 339 delay: {isNumber: true}, | |
| 340 endDelay: {isNumber: true}, | |
| 341 fill: {}, | |
| 342 iterationStart: {isNumber: true}, | |
| 343 iterations: {isNumber: true, allowInfinity: true}, | |
| 344 duration: {isNumber: true}, | |
| 345 playbackRate: {isNumber: true}, | |
| 346 direction: {}, | |
| 347 easing: {} | |
| 348 }; | |
| 349 for (t in timing) { | |
| 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]; | |
| 354 } | |
| 355 } | |
| 356 return props; | |
| 357 }, | |
| 358 | |
| 359 get animationEffect() { | |
| 360 var props = {}; | |
| 361 var frames = []; | |
| 362 var effect; | |
| 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 && this.shadowRoot) { | |
| 368 children = this.shadowRoot.querySelectorAll('core-animation-keyfra
me'); | |
| 369 } | |
| 370 Array.prototype.forEach.call(children, function(c) { | |
| 371 frames.push(c.properties); | |
| 372 }); | |
| 373 } | |
| 374 if (this.customEffect) { | |
| 375 effect = this.customEffect; | |
| 376 } else { | |
| 377 // effect = new KeyframeEffect(frames, this.composite); | |
| 378 effect = frames; | |
| 379 } | |
| 380 return effect; | |
| 381 }, | |
| 382 | |
| 383 animationFinishHandler: function() { | |
| 384 this.fire('core-animation-finish'); | |
| 385 } | |
| 386 | |
| 387 }); | |
| 388 })(); | |
| 389 ; | |
| 390 | |
| 391 Polymer('core-animation-keyframe',{ | |
| 392 publish: { | |
| 393 /** | |
| 394 * An offset from 0 to 1. | |
| 395 * | |
| 396 * @property offset | |
| 397 * @type Number | |
| 398 */ | |
| 399 offset: {value: null, reflect: true} | |
| 400 }, | |
| 401 get properties() { | |
| 402 var props = {}; | |
| 403 var children = this.querySelectorAll('core-animation-prop'); | |
| 404 Array.prototype.forEach.call(children, function(c) { | |
| 405 props[c.name] = c.value; | |
| 406 }); | |
| 407 if (this.offset !== null) { | |
| 408 props.offset = this.offset; | |
| 409 } | |
| 410 return props; | |
| 411 } | |
| 412 }); | |
| 413 ; | |
| 414 | |
| 415 Polymer('core-animation-prop',{ | |
| 416 publish: { | |
| 417 /** | |
| 418 * A CSS property name. | |
| 419 * | |
| 420 * @property name | |
| 421 * @type string | |
| 422 */ | |
| 423 name: {value: '', reflect: true}, | |
| 424 | |
| 425 /** | |
| 426 * The value for the CSS property. | |
| 427 * | |
| 428 * @property value | |
| 429 * @type string|number | |
| 430 */ | |
| 431 value: {value: '', reflect: true} | |
| 432 } | |
| 433 }); | |
| 434 | |
| OLD | NEW |