forked from w3c/web-animations
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOverview.src.html
More file actions
6873 lines (5467 loc) · 271 KB
/
Overview.src.html
File metadata and controls
6873 lines (5467 loc) · 271 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<h1>Web Animations</h1>
<pre class='metadata'>
Status: ED
Shortname: web-animations
ED: http://w3c.github.io/web-animations/
TR: http://www.w3.org/TR/web-animations/
Previous version: http://www.w3.org/TR/2014/WD-web-animations-20140605/
Previous version: http://www.w3.org/TR/2013/WD-web-animations-20130625/
Version history: https://github.com/w3c/web-animations/commits/master
Level: 1
Group: fxtf
Editor: Brian Birtles, Mozilla Japan, bbirtles@mozilla.com
Editor: Shane Stephens, Google Inc, shans@google.com
Editor: Alex Danilo, Google Inc, adanilo@google.com
Editor: Tab Atkins, Google Inc, jackalmage@gmail.com
Abstract: This specification defines a model for synchronization and
timing of changes to the presentation of a Web page.
This specification also defines an application programming interface
for interacting with this model and it is expected that further
specifications will define declarative means for exposing these
features.
Ignored Terms: double, boolean, DOMString, unsigned long, unrestricted double, (animationeffect or effectcallback), SVGPathSegList, (unrestricted double or DOMString)
Link Defaults: dom-core-ls (interface) event, dom-core-ls (interface) document, cssom-1 (interface) pseudoelement
</pre>
<link href='http://dev.w3.org/fxtf/default.css' rel='stylesheet' test='text/css'>
<link href='web-animations.css' rel='stylesheet' type='text/css'>
<script src='MathJax/MathJax.js?config=MML_SVGorMML,local/local' type='text/javascript'></script>
<h2 id="introduction">Introduction</h2>
<div class='informative-bg'><em>This section is non-normative</em>
Web Animations defines a model for supporting animation and
synchronization on the Web platform.
It is intended that other specifications will build on this model and
expose its features through declarative means.
In addition, this specification also defines a programming interface to
the model that may be implemented by user agents that provide support
for scripting.
<h3 id="use-cases">Use cases</h3>
The Web Animations model aims at two broad areas of application:
: User interface effects
:: Animation can be used to give visual clues and feedback to make
a user interface more readily comprehensible.
For example, a user action results in a table row being
removed to represent an item being removed from a shopping cart.cd -
In such a case, fading the row to transparent and then shifting
the subsequent rows up to fill the space over a few hundred
milliseconds provides the user with clear feedback as to the
results of their action as opposed to instantly removing the row
from the DOM.
To support this scenario not only are the animated effects of
fading and shifting required, but so is synchronization, both
between the animations, and between animations and scripted
actions (removing the table row from the DOM after the animations
have completed).
: Storytelling and visualization
:: Another type of animation uses the animated effect to convey
a story or represent some information.
Unlike user interface effects which are largely a presentational
adjunct to the content, these animations form an essential part of
the content presented to the user.
For example, in an animated cartoon two cats fly through space
to another planet leaving a rainbow trail behind them.
After arriving at the planet a change of scene occurs and the user
should decide whether or not the cats enter a magic mountain by
selecting one of two preset destinations in the scene.
This scenario requires the following features:
* animated effects for moving characters along a path as well as
warping a path (the rainbow trail),
* synchronization that allows some actions to happen
simultaneously (the two cats moving) and others in sequence
(the change of scene),
* play control to allow rewinding the cartoon, or changing its
playback rate to accommodate particular learning or
accessibility needs,
* the ability to trigger animations in response to user input
Similar use cases in this category include visualising physical
phenomena such as spring motion for educational purposes,
or visualising data such as the prevalence of a disease over
a geographical space over a year whereby animation is used to
present the time-based component of the data.
<h3 id="relationship-to-other-specifications">Relationship to other specifications</h3>
CSS Transitions [[CSS3-TRANSITIONS]], CSS Animations [[CSS3-ANIMATIONS]], and
SVG [[SVG11]] all provide mechanisms that
generate animated content on a Web page.
Although the three specifications provide many similar features,
they are described in different terms.
This specification proposes an abstract animation model that
encompasses the common features of all three specifications.
This model is backwards-compatible with the current behavior of these
specifications such that they can be defined in terms of this model
without any observable change.
The animation features in SVG 1.1 are defined in terms of SMIL
Animation [[SMIL-ANIMATION]].
It is intended that by defining SVG's animation features in terms of
the Web Animations model, the dependency between SVG and SMIL
Animation can be removed.
As with Timing control for script-based animations (commonly referred
to as “requestAnimationFrame”) [[ANIMATION-TIMING]],
the programming interface component of this specification allows
animations to be created from script.
The animations created using the interface defined in this
specification, however, once created, are executed entirely by the
user agent meaning they share the same performance characteristics as
animations defined by markup.
Using this interface it is possible to create animations
from script in a simpler and more performant manner.
The time values used within the programming interface
correspond with those used in Timing control for script-based
animations [[ANIMATION-TIMING]] and their execution order is defined
such that the two interfaces can be used simultaneously without conflict.
The programming interface component of this specification makes
some additions to interfaces defined in HTML5 [[HTML5]].
<h3 id="overview-of this-specification">Overview of this specification</h3>
This specification begins by defining an abstract model for animation.
This is followed by a programming interface defined in terms of the
abstract model.
The programming interface is defined in terms of the abstract model
and is only relevant to user agents that provide scripting support.
</div>
<h2 id="web-animations-model-overview">Web Animations model overview</h2>
<div class='informative-bg'><em>This section is non-normative</em>
At a glance, the Web Animations model consists of two largely
independent pieces, a <em>timing model</em> and an <em>animation
model</em>. The role of these pieces is as follows:
: Timing model
:: Takes a moment in time and converts it to a proportional distance
within a single iteration of an animation called the <em>time
fraction</em>.
An <em>iteration index</em> is also generated for animations
that vary as they repeat.
: Animation model
:: Takes the <em>time fractions</em> and <em>iteration indices</em>
produced by the timing model and converts them into a series of values
to apply to the target properties and attributes.
Graphically, this flow can be represented as follows:
<div class="figure">
<img src="img/timing-and-animation-models.svg" width="600" alt="Overview of the operation of the Web Animations model.">
</div>
<p class="caption">
Overview of the operation of the Web Animations model.<br>
The current time is input to the timing model which produces a time
fraction and an iteration index.<br>
These parameters are used as input to the animation model which produces
the values to apply.<br>
</p>
For example, consider an animation that:
* starts after 3 seconds
* runs twice,
* takes 2 seconds every time, and
* changes the width of a rectangle from 50 pixels to 100 pixels.
The first three points apply to the timing model.
At a time of 6 seconds, it will calculate that the animation should be
half-way through its second iteration and produces the result 0.5.
The animation model then uses that information to calculate a width
This specification begins with the timing model and then proceeds to
the animation model.
</div>
<h2 id="timing-model">Timing model</h2>
This section describes and defines the behavior of the Web Animations
timing model.
<h3 id="the-timing-model-at-a-glance">The timing model at a glance</h3>
<div class='informative-bg'>
<em>This section is non-normative</em>
Two features characterise the Web Animations timing model: it is
<em>stateless</em> and it is <em>hierarchical</em>.
<h4 id="stateless">Stateless</h4>
The Web Animations timing model operates by taking an input time and
producing an output time fraction.
Since the output is based solely on the input time and is independent
of previous inputs, the model may be described as stateless.
This gives the model the following properties:
: Frame-rate independent
:: Since the output is independent of previous inputs, the rate at
which the model is sampled will not affect its progress.
Provided the input times are proportional to the progress of
real-world time, animations will progress at an identical rate
regardless of the capabilities of the device running them.
: Direction-agnostic
:: Since the sequence of inputs is insignificant, the model is
directionless.
This means that the model can be sampled in reverse or even in
a backwards and forwards pattern without requiring any specialized
handling.
: Constant-time seeking
:: Since each input is independent of the previous input, the
processing required to perform a seek operation, even far into the
future, is at least potentially constant.
There are a few exceptions to the stateless behavior of the timing
model.
Firstly, a number of methods defined in the <a
href="#programming-interface" section>programming interface</a> to the model
provide play control such as pausing an animation.
These methods are defined in terms of the time at which they are
called and are therefore stative.
These methods are provided primarily for convenience and are not part
of the core timing model but are layered on top.
Similarly, the <a href="#reaching-the-end" section>finishing behavior</a> of
players means that dynamic changes to the end time of
the media (source content) of a player may produce a different result
depending on when the change occurs.
This behavior is somewhat unfortunate but has been deemed intuitive
and consistent with HTML.
As a result, the model can only truly be described as stateless
<em>in the absence of dynamic changes to its timing properties</em>.
Finally, each time the model is sampled, it can be considered to
establish a temporary state.
While this temporary state affects the values returned from the <a
href="#programming-interface" section>programming interface</a>, it has no
influence on the subsequent samples and hence does not conflict with
the stateless qualities described above.
<h4 id="hierarchical">Hierarchical</h4>
The other characteristic feature of the Web Animations timing model is
that time is inherited.
Time begins with a monotonically increasing time source and cascades
down a number of steps to each animation.
At each step, time may be shifted backwards and forwards, scaled,
reversed, paused, and repeated.
<div class="figure">
<img src="img/time-hierarchy.svg" width="600"
alt="A hierarchy of timing nodes">
</div>
<p class="caption">
A hierarchy of timing nodes.
Each node in the tree derives its time from its parent node.
At the root of the tree is the global clock.
</p>
A consequence of this hierarchical arrangement is that complex
animation arrangements can be reversed, scheduled, accelerated and so
on as a whole unit since the manipulations applied to the parent
cascade down to its <a>descendants</a>.
Furthermore, since time has a common source, it is easy to synchronize
animations.
</div>
<h3 id="timing-model-concepts">Timing model concepts</h3>
In Web Animations, timing is based on a hierarchy of time relationships
between timing nodes.
Parent nodes provide timing information to their child nodes in the form
of <a>time values</a>.
A <dfn>time value</dfn> is a real number which nominally represents
a number of milliseconds from some moment.
The connection between <a>time values</a> and wall-clock milliseconds
may be obscured by any number of transformations applied to the value as
it passes through the time hierarchy.
<p class="annotation">
In the future we may have timelines that are based on UI gestures in
which case the connection between time values and milliseconds will be
weakened even further.
</p>
A <a>time value</a> may also be <dfn>unresolved</dfn> if, for example,
a timing node is not in a state to produce a <a>time value</a>.
Periodically, the user agent will queue a task to update the timing
model in a process called <dfn>sampling</dfn>.
On each <dfn title='single-sample'>sample</dfn> the
<a>time values</a> of each timing node are updated.
Note: A more precise definition of when the model is updated when scripting is
involved is provided in <a
href="#script-execution-and-live-updates-to-the-model"
section></a>.
<h3 id="the-global-clock">The global clock</h3>
At the root of the Web Animations timing hierarchy is the <a>global
clock</a>.
The <dfn>global clock</dfn> is a source of monotonically increasing
<a>time values</a> unaffected by adjustments to the system clock.
The <a>time values</a> produced by the <a>global clock</a> represent
wall-clock milliseconds from an unspecified historical moment.
Because the zero time of the <a>global clock</a> is not specified,
the absolute values of the <a>time values</a> produced by the <a>global
clock</a> are not significant, only their rate of change.
Note: The <a>global clock</a> is not exposed in the <a
href="#programming-interface">programming interface</a> and nor is it
expected to be exposed by markup.
As a result the moment from which <a>global clock</a> <a>time values</a>
are measured, that is, the zero time of the clock, is
implementation-dependent.
One user agent may measure the number of milliseconds since the the user
agent was loaded whilst another may use the time when the device was
started.
Both approaches are acceptable and produce no observable difference
in the output of the model.
<h3 id="timelines">Timelines</h3>
A <dfn>timeline</dfn> provides a source of <a>time values</a> for the
purpose of synchronization.
Typically, a <a>timeline</a> is tied to the <a>global clock</a> such
that its absolute time is calculated as a fixed offset from the time of
the <a>global clock</a>.
This offset is established by designating some moment as the timeline's
<dfn>zero time</dfn> and recording the <a>time value</a> of the
<a>global clock</a> at that moment.
At subsequent moments, the <a>time value</a> of the timeline is
calculated as the difference between the current <a>time value</a> of
the <a>global clock</a> and the value recorded at the <a>zero time</a>.
<p class="annotation">
Note that we anticipate that other types of timelines may be introduced
in the future that are not tied to the global clock.
For example, a timeline whose time values are related to the progress of
a UI gesture.
</p>
Since a <a>timeline</a> may be defined relative to a moment that has yet
to occur, it may not always be able to return a meaningful <a>time
value</a>, but only an <a>unresolved</a> time value.
A <a>timeline</a> is considered to be
<dfn title="inactive timeline">inactive</dfn>
when its <a>time value</a> is <a>unresolved</a>.
<h4 id="the-document-timeline">The document timeline</h4>
Each document has a <a>timeline</a> called the <dfn>document
timeline</dfn>.
The <a>time values</a> of the <a>document timeline</a> are calculated
as a fixed offset from the <a>global clock</a> such that the <a>zero
time</a> corresponds to the <a
href="http://www.w3.org/TR/navigation-timing/#dom-performancetiming-navigationstart">
<code>navigationStart</code></a> moment [[!NAVIGATION-TIMING]].
Prior to this moment, the <a>document timeline</a> is
<a title="inactive timeline">inactive</a>.
<div class="informative-bg"><em>This section is non-normative</em>
Since the <a>document timeline</a> is tied to the <a>global
clock</a> by a fixed offset, <a>time values</a> reported by the
<a>document timeline</a> increase monotonically.
Furthermore, since no scaling is applied, these <a>time values</a>
are proportional to wall-clock milliseconds.
Since the <a>time values</a> of the <a>document timeline</a> are
relative to the <code>navigationStart</code> time,
<code>document.timeline.currentTime</code> will roughly correspond to
<a href="http://www.w3.org/TR/hr-time/#dom-performance-now">
<code>Performance.now()</code></a>
[[HR-TIME]] with the exception that
<code>document.timeline.currentTime</code> does not change within
a script execution block as defined in <a
href="#script-execution-and-live-updates-to-the-model" section></a>.
</div>
<h3 id="players">Players</h3>
<div class="informative-bg"><em>This section is non-normative</em>
The children of a <a>timeline</a> are called <em>players</em>.
A player takes an <a>animation node</a> which is a static
description of some timed behavior and binds it to a <a>timeline</a>
so that it runs.
A player also allows run-time control of the connection between the
<a>animation node</a> and its <a>timeline</a> by providing pausing,
seeking, and speed control.
The relationship between a player and an <a>animation node</a> is
analogous to that of a DVD player and a DVD.
</div>
A <dfn>player</dfn> connects a single <a>animation node</a>, called
its <dfn>source content</dfn>, to a <a>timeline</a> and provides
playback control.
Both of these associations are optional and configurable such that
a <a>player</a> may have no associated <a>source content</a> or
<a>timeline</a> at a given moment.
A <a>player</a>'s <dfn title="player start time">start time</dfn> is the
<a>time value</a> of its <a>timeline</a> when its <a>source content</a>
is scheduled to begin playback. A player's <a
title="player start time">start time</a> is initially
<a>unresolved</a>.
A <a>player</a> also maintains a <dfn>hold time</dfn> <a>time value</a>
which is used to fix the player's output <a>time value</a>, called its
<a>current time</a>, in circumstances such as pausing</a>.
The <a>hold time</a> is initially <a>unresolved</a>.
When a <a>player</a> is created, it is assigned a globally unique
sequence number called the <dfn>player sequence number</dfn>.
This number is used to resolve the sort order of players for a variety
of situations such as combining animations and returning the list of
current players.
Issue: Should this actually be based on when the player is attached to
a timeline? Or when it leaves the idle state?
<h4 id="setting-the-timeline">Setting the timeline of a player</h4>
The procedure to <dfn>set the timeline of a player</dfn>, <var>player</var>,
to <var>new timeline</var> which may be null, is as follows:
1. Let <var>old timeline</var> be the current <a>timeline</a> of
<var>player</var>, if any.
2. If <var>new timeline</var> is the same object as <var>old timeline</var>,
abort this procedure.
3. If <var>new timeline</var> is null and <var>old timeline</var> is not null,
run the procedure to <a>reset a player's pending tasks</a> on
<var>player</var>.
<p class="note">
Note that if <var>new timeline</var> is not null and <var>player</var> has
a <a>pending play task</a> or a <a>pending pause task</a> no special
handling is required: the pending task will run as soon as the
<a>player</a> is <a>ready</a> even though this may occur at a different
moment than it might have done with the old timeline.
</p>
6. Let the <a>timeline</a> of <var>player</var> be <var>new timeline</var>.
7. <p class="todo">
If <var>new timeline</var> is null, ensure that <a>custom effects</a> get
called with an <a>unresolved</a> <a>time fraction</a> (unless a subsequent
change in the same script execution context makes this redundant).
</p>
8. Run the procedure to <a>update a player's finished state</a> for
<var>player</var>.
<p class=todo>
Update this to preserve the player's <a>current time</a>.
</p>
The procedure to <dfn>reset a player's pending tasks</dfn> for <var>player</var>
is as follows:
1. If <var>player</var> has a <a>pending play task</a>, cancel that task.
2. If <var>player</var> has a <a>pending pause task</a>, cancel that task.
3. <a title="reject a Promise">Reject</a> <var>player</var>'s <a>current ready
promise</a> with a DOMException named "AbortError".
4. Let <var>player</var>'s <a>current ready promise</a> be the result of
<a title="create a new resolved Promise">creating a new resolved Promise
object</a>.
<h4 id="setting-the-source-content">Setting the source content of a
player</h4>
The procedure to <dfn>set the source content of a player</dfn>,
<var>player</var>, to <var>new content</var> which may be null, is as follows:
1. Let <var>old content</var> be the current <a>source content</a> of
<var>player</var>, if any.
2. If <var>new content</var> is the same object as <var>old content</var>,
abort this procedure.
3. If <var>new content</var> is null and <var>old content</var> is not null,
run the procedure to <a>reset a player's pending tasks</a> on
<var>player</var>.
4. If <var>player</var> has a <a>pending pause task</a>, reschedule that task
to run as soon as <var>player</var> is <a>ready</a>.
5. If <var>player</var> has a <a>pending play task</a>, reschedule that task
to run as soon as <var>player</var> is <a>ready</a> to play <var>new
content</var>.
6. If <var>new content</var> is not <code>null</code> and
if <var>new content</var> has a <a>parent animation group</a>,
<a title="remove an animation node">remove</a> <var>new content</var> from
its <a>parent animation group</a>.
7. If <var>new content</var> is not <code>null</code> and
if <var>new content</var> is the <a>source content</a> of another
<a>player</a>, <var>previous player</var>, run the procedure to <a>set the
source content of a player</a> (this procedure) on <var>previous
player</var> passing null as <var>new content</var>.
8. Let the <a>source content</a> of <var>player</var> be <var>new
content</var>.
9. If <var>old content</var> is not <code>null</code>, queue a task to call any
<a>custom effects</a> associated with <a>inclusive descendants</a> of
<var>old content</var> with an <a>unresolved</a> <a>time fraction</a>.
<div class="issue">
This is not quite right. If <var>old content</var> is attached to another
player in the same task then we should probably not do an extra
callback with <a>unresolved</a>.
The definition of when <a>custom effects</a> gets called needs to be
audited and probably rewritten.
</div>
10. Run the procedure to <a>update a player's finished state</a> for
<var>player</var>.
<h4 id="the-current-time-of-a-player">The current time of a player</h4>
<a>Players</a> provide a <a>time value</a> to their <a>source
content</a> called the player's <dfn>current time</dfn>.
The <a>current time</a> is calculated from the first
matching condition from below:
<div class="switch">
: If the player's <a>hold time</a> is <a title="unresolved">resolved</a>,
:: The <a>current time</a> is the player's <a>hold time</a>.
: If <em>any</em> of the following are true:
1. the player has no associated <a>timeline</a>, or
2. the associated <a>timeline</a> is
<a title="inactive timeline">inactive</a>, or
3. the player's <a title="player start time">start time</a> is
<a>unresolved</a>.
:: The <a>current time</a> is an <a>unresolved</a> time value.
: Otherwise,
::
<blockquote>
<code><a>current time</a> =
(<var>timeline time</var> - <a
title="player start time">start time</a>)
× <a title="player playback rate">playback rate</a></code>
</blockquote>
Where <var>timeline time</var> is the current <a>time value</a> of
the associated <a>timeline</a>.
The <a title="player playback rate">playback rate</a> value is
defined in <a href="#speed-control" section></a>.
</div>
<h4 id="setting-the-current-time-of-a-player">Setting the current time of a player</h4>
The <a>current time</a> of a player can be set to a new value to
<em>seek</em> the player.
The procedure for setting the current time is split into two parts.
The procedure to <dfn>silently set the current time</dfn> of
a player, <var>player</var>, to <var>seek time</var> is as follows:
1. If <var>seek time</var> is an <a>unresolved</a> time value,
<a href="http://heycam.github.io/webidl/#dfn-throw">throw</a> a
NotSupportedError.
2. Update either <var>player</var>'s <a>hold time</a> or <a
title="player start time">start time</a> as follows:
<div class="switch">
: If <em>any</em> of the following conditions are true:
* <var>player</var>'s <a>hold time</a> is
<a title="unresolved">resolved</a>, or
* <var>player</var> has no associated <a>timeline</a> or the
associated <a>timeline</a> is
<a title="inactive timeline">inactive</a>, or
* <var>player</var>'s
<a title="player playback rate">playback rate</a> is 0, or
* <var>player</var> has a <a>pending pause task</a>
:: Set <var>player</var>'s <a>hold time</a> to <var>seek time</var>.
: Otherwise,
:: Set <var>player</var>'s <a title="player start time">start time</a> to
the result of evaluating
<code><var>timeline time</var> - (<var>seek time</var> / <a
title="player playback rate">playback rate</a>)</code>
where <var>timeline time</var> is the current <a>time value</a>
of <a>timeline</a> associated with <var>player</var>.
</div>
1. If <var>player</var> has no associated <a>timeline</a> or the associated
<a>timeline</a> is <a title="inactive timeline">inactive</a>,
make <var>player</var>'s <a title="player start time">start time</a>
<a>unresolved</a>.
<p class=annotation>
This preserves the invariant that when we don't have an active timeline it
is only possible to set <em>either</em> the <a>player start time</a>
<em>or</em> the player's <a>current time</a>.
</p>
4. Make <var>player</var>'s <a>previous current time</a> <a>unresolved</a>.
The procedure to <dfn>set the current time</dfn> of a player,
<var>player</var>, to <var>seek time</var> is as follows:
1. Run the steps to <a>silently set the current time</a> of
<var>player</var> to <var>seek time</var>.
2. If <var>player</var> has a <a>pending pause task</a>, cancel the
task and <a title="resolve a Promise">resolve</a> <var>player</var>'s
<a>current ready promise</a> with <var>player</var>.
3. Run the procedure to <a>update a player's finished state</a>
for <var>player</var>.
<h4 id='setting-the-start-time-of-a-player'>Setting the start time of a player</h4>
The procedure to <dfn>update the player start time</dfn>
of <a>player</a>, <var>player</var>, to
<a title="player start time">start time</a>, <var>new start time</var>,
is as follows:
1. Let <var>timeline time</var> be the current <a>time value</a> of the
<a>timeline</a> that <var>player</var> is associated with.
If there is no <a>timeline</a> associated with <var>player</var> or the
associated timeline is <a title="inactive timeline">inactive</a>,
let the <var>timeline time</var> be <a>unresolved</a>.
1. If <var>timeline time</var> is <a>unresolved</a> and <var>new start
time</var> is <a title="unresolved">resolved</a>, make <var>player</var>'s
<a>hold time</a> <a>unresolved</a>.
<p class=annotation>
This preserves the invariant that when we don't have an active timeline it
is only possible to set <em>either</em> the <a>player start time</a>
<em>or</em> the player's <a>current time</a>.
</p>
1. Let <var>previous current time</var> be <var>player</var>'s <a>current
time</a>.
Note: This is the <a>current time</a> after applying the changes from the
previous step which may cause the <a>current time</a> to become
<a>unresolved</a>.
1. Set <var>player</var>'s <a title="player start time">start time</a> to
<var>new start time</var>.
1. Update <var>player</var>'s <a>hold time</a> based on the first matching
condition from the following,
<div class="switch">
: If <var>new start time</var> is <a title="unresolved">resolved</a>,
:: If <var>player</var>'s <a title="player playback rate">playback rate</a>
is not zero, make <var>player</var>'s <a>hold time</a>
<a>unresolved</a>.
: Otherwise (<var>new start time</var> is <a>unresolved</a>),
:: Set <var>player</var>'s <a>hold time</a> to <var>previous current
time</var> even if <var>previous current time</var> is
<a>unresolved</a>.
</div>
1. If <var>player</var> has a <a>pending play task</a> or
a <a>pending pause task</a>, cancel that task and
<a title="resolve a Promise">resolve</a> <var>player</var>'s
<a>current ready promise</a> with <var>player</var>.
1. Run the procedure to <a>update a player's finished state</a>
for <var>player</var>.
<h4 id='waiting-for-source-content'>Waiting for source content</h4>
<div class='informative-bg'>
<em>This section is non-normative</em>
Some operations performed by a <a>player</a> may not occur
instantaneously.
For example, some user agents may delegate the playback of an
animation to a separate process or to specialized graphics hardware
each of which may incur some setup overhead.
If such an animation is timed from the moment when the animation was
triggered there may be a significant jump between the first and second
frames of the animation corresponding to the setup time involved.
To avoid this problem, Web Animations typically begins timing
animations from the moment when the first frame of the animation is
complete.
This is represented by an <a>unresolved</a> <a
title="player start time">start time</a> on the <a>player</a> which becomes
resolved when the player is <a>ready</a>.
Content may opt out of this behavior by setting the <a
title="player start time">start time</a>
to a <a title="unresolved">resolved</a> <a>time value</a>.
</div>
A player is <dfn>ready</dfn> at the first moment where <em>both</em> of the
following conditions are true:
* the user agent has completed any setup required to begin the playback of
each <a>inclusive descendant</a> of the player's <a>source content</a>
including rendering the first frame of any <a>animation</a> with an
associated <a>animation effect</a> or executing any <a>custom effects</a>
associated with such an <a>animation</a>.
* the player is associated with a <a>timeline</a> that is not
<a title="inactive timeline">inactive</a>.
<h4 id='promise-objects'>Promise objects</h4>
<dfn>Promise</dfn> objects are defined by [[!ECMA-262]], <a
href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-objects">section
25.4</a>.
To <dfn>resolve a Promise</dfn> with <var>value</var>,
call the \[[Call]] internal method of \[[Resolve]] on the <a
href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promisecapability-records">Promise
capability</a> record for the promise, passing <code>undefined</code> as
<var>thisArgument</var> and (<var>value</var>) as <var>argumentsList</var>.
To <dfn>reject a Promise</dfn> with <var>reason</var>,
call the \[[Call]] internal method of \[[Reject]] on the <a
href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promisecapability-records">Promise
capability</a> record for the promise, passing <code>undefined</code> as
<var>thisArgument</var> and (<var>reason</var>) as <var>argumentsList</var>.
To <dfn>create a new resolved Promise</dfn> with <var>value</var>, call <a
href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.resolve">Promise.resolve</a>,
passing <var>value</var> as <var>x</var>.
<h4 id='the-current-ready-promise'>The current ready promise</h4>
Each <a>player</a> has a <dfn>current ready promise</dfn>.
The <a>current ready promise</a> is initially a resolved <a>Promise</a> created
using the procedure to <a>create a new resolved Promise</a>.
The object is replaced with a new <a>Promise</a> object every time the player
enters the <a>pending play state</a> as well as when the player is
cancelled (see <a href="#cancelling-a-player-section" section></a>).
<div class="note">
Note that since the same object is used for both pending play and
pending pause requests, authors are advised to check the state of the
player when the <a>Promise</a> is resolved.
For example, in the following code fragment, the state of the player
will be <a title="running play state">running</a> when the
<a>current ready promise</a> is resolved.
This is because the player does not leave the <a>pending play state</a>
in between the calls to <code>pause</code> and
<code>play</code> and hence the <a>current ready promise</a> does
not change.
<pre class='example sh_javascript'>
player.pause();
player.ready.then(function() {
// Displays 'running'
alert(player.playState);
});
player.play();
</pre>
</div>
<h4 id='playing-a-player-section'>Playing a player</h4>
The procedure to <dfn>play a player</dfn>, <var>player</var>, is as follows:
1. Let <var>has pending ready promise</var> be a boolean flag that is
initially false.
2. If <var>player</var> has a <a>pending play task</a>,
1. Cancel that task.
2. Set <var>has pending ready promise</var> to true.
3. If <var>player</var> has a <a>pending pause task</a>,
1. Cancel that task.
2. If <var>player</var> has an associated <a>timeline</a> that is not
<a title="inactive timeline">inactive</a>, perform the following steps:
1. Set <var>player</var>'s <a title="player start time">start time</a>
to the result of evaluating <code><var>timeline time</var> -
<a>hold time</a> / <a title="player playback rate">playback
rate</a></code>
where <var>timeline time</var> is the current <a>time value</a> of
the <a>timeline</a> associated with <var>player</var>.
2. Let <var>player</var>'s <a>hold time</a> be <a>unresolved</a>.
3. Set <var>has pending ready promise</var> to true.
4. Perform the steps corresponding to the <em>first</em> matching
condition from the following, if any:
<div class="switch">
: If <a>player playback rate</a> > 0 and <em>either</em>
<var>player</var>'s:
* <a>current time</a> is <a>unresolved</a>, or
* <a>current time</a> < zero, or
* <a>current time</a> ≥ <a>source content end</a>,
:: Set <var>player</var>'s <a>hold time</a> to zero.
: If <a>player playback rate</a> < 0 and <em>either</em>
<var>player</var>'s:
* <a>current time</a> is <a>unresolved</a>, or
* <a>current time</a> ≤ zero, or
* <a>current time</a> > <a>source content end</a>,
:: set <var>player</var>'s <a>hold time</a> to <a>source content end</a>.
: If <a>player playback rate</a> = 0 and <var>player</var>'s
<a>current time</a> is <a>unresolved</a>,
:: Set <var>player</var>'s <a>hold time</a> to zero.
</div>
5. If <var>player</var>'s <a>hold time</a> is <a>unresolved</a>, perform the
following steps:
1. If <var>has pending ready promise</var> is true,
<a title="resolve a Promise">resolve</a> <var>player</var>'s <a>current
ready promise</a> with <var>player</var>.
2. Abort this procedure.
6. Let <var>player</var>'s <a title="player start time">start time</a> be
<a>unresolved</a>.
7. If <var>has pending ready promise</var> is false,
let <var>player</var>'s <a>current ready promise</a> be a new
(pending) <a>Promise</a> object.
8. Schedule a task to run as soon as <var>player</var> is <a>ready</a>.
The task shall perform the following steps:
1. <a>Assert</a> that <a>hold time</a> is <a
title="unresolved">resolved</a>. (This is because we don't queue this
task if <a>hold time</a> is <a>unresolved</a> and anything that causes
it to become <a>unresolved</a> while this task is queued, should cancel
this task.)
1. Let <var>ready time</var> be the <a>time value</a> of
the <a>timeline</a> associated with <var>player</var> at the moment
when <var>player</var> became <a>ready</a>.
2. Let <var>new start time</var> be the result of evaluating
<code><var>ready time</var> - <a>hold time</a> / <a>player
playback rate</a></code> for <var>player</var>.
If the <a>player playback rate</a> is zero, let <var>new start
time</var> be simply <var>ready time</var>.
3. If <var>player</var>'s <a title="player playback rate">playback rate</a>
is not 0, make <var>player</var>'s <a>hold time</a> <a>unresolved</a>.
4. Set the <a>player start time</a> of <var>player</var>
to <var>new start time</var>.
5.
<div class="todo">Queue a task here for sampling custom effects.
(This should happen before we resolve the ready promise.)
</div>
6. <a title="resolve a Promise">Resolve</a> <var>player</var>'s <a>current
ready promise</a> with <var>player</var>.
7. Run the procedure to <a>update a player's finished state</a>
for <var>player</var>.
<div class="annotation">
Note that the order of the above two steps is important
since it means that a player with zero-length <a>source
content</a> will resolve its <a>current ready promise</a>
before its <a>current finished promise</a>.
</div>
So long as the above task is scheduled but has yet to run,
<var>player</var> is described as having a
<dfn>pending play task</dfn>.
A user agent MAY execute the above task immediately (if it
determines <var>player</var> is immediately <a>ready</a>) thereby
bypassing the <a>pending play state</a> altogether.
9. Run the procedure to <a>update a player's finished state</a>
for <var>player</var>.
<h4 id='pausing-a-player-section'>Pausing a player</h4>
Whenever a <a>player</a> has an <a>unresolved</a> <a title="player start
time">start time</a>, its <a>current time</a> will be suspended.
As with <a title="play a player">playing a player</a>, pausing may not happen
instantaneously (see <a href="#waiting-for-source-content" section></a>).
For example, if animation is performed by a separate process, it may
be necessary to synchronize the <a>current time</a> to ensure that it
reflects the state drawn by the animation process.
The procedure to <dfn>pause a player</dfn>, <var>player</var> is as follows:
1. If <var>player</var> has a <a>pending pause task</a>, abort these steps.
1. Let <var>has pending ready promise</var> be a boolean flag that is
initially false.
1. If <var>player</var> has a <a>pending play task</a>, cancel that task
and let <var>has pending ready promise</var> be true.
1. Set <var>player</var>'s <a>hold time</a> to <a>current time</a>.
1. If <var>has pending ready promise</var> is false,
set <var>player</var>'s <a>current ready promise</a> to a new
(pending) <a>Promise</a> object.
1. Schedule a task to be executed at the first possible moment after
the user agent has performed any processing necessary to suspend
the playback of any animations that are <a>inclusive
descendants</a> of <var>player</var>'s <a>source content</a>, if any.
The task shall perform the following steps:
1. Set <var>player</var>'s <a>hold time</a> to its <a>current time</a>
(even if the current time is <a>unresolved</a>).
1. Make <var>player</var>'s <a title="player start time">start time</a>
unresolved.
1.
<div class="todo">Queue a task here for sampling custom effects
with the final current time. (This should happen before we
resolve the ready promise).
</div>
1. <a title="resolve a Promise">Resolve</a> <var>player</var>'s <a>current
ready promise</a> with <var>player</var>.
1. Run the procedure to <a>update a player's finished state</a>
for <var>player</var>.
So long as the above task is scheduled but has yet to run,
<var>player</var> is described as having a <dfn>pending pause task</dfn>.
While the task is running, however, <var>player</var> does
<em>not</em> have a <a>pending pause task</a>.
1. Run the procedure to <a>update a player's finished state</a>
for <var>player</var>.
<h4 id="reaching-the-end">Reaching the end</h4>
<div class='informative-bg'>
<em>This section is non-normative</em>
Players in the real world such as DVD players or cassette players
typically continue playing until they reach the end of their media
at which point they stop.
If such players are able to play in reverse, they typically stop
playing when they reach the beginning of their media.
In order to emulate this behavior and to provide consistency
with HTML's <a
href="http://www.w3.org/TR/html5/embedded-content-0.html#media-elements">media
elements</a> [[HTML5]], the <a>current time</a> of Web Animations'
players do not play forwards beyond the <a>end time</a> of their
<a>source content</a> or play backwards past time zero.
A player that has reached the natural boundary of its playback range
is said to have <em>finished</em>.
Graphically, the effect of limiting the current time is shown below.
<div class="figure">
<img src="img/limiting.svg" width="500"
alt="The effect of limiting the current time of a player.">
</div>
<p class="caption">
The effect of limiting the <a>current time</a> of a <a>player</a>
with a start time of 1s, a source content of length 3s, and
a positive <a>player playback rate</a>.
After the <a>current time</a> of the player reaches the end of the
source content, it is capped at 3s.
</p>
It is possible, however, to <em>seek</em> the <a>current time</a> of
a <a>player</a> to a time past the end of the <a>source content</a>.
When doing so, the <a>current time</a> will not progress but the