Fri, 15 Mar 2013 15:17:54 +0900
Start reworking Animation values/effects section
web-anim/index.html | file | annotate | diff | comparison | revisions |
1.1 --- a/web-anim/index.html Thu Mar 14 21:41:18 2013 -0700 1.2 +++ b/web-anim/index.html Fri Mar 15 15:17:54 2013 +0900 1.3 @@ -2550,16 +2550,17 @@ 1.4 <h2>Animations</h2> 1.5 <p> 1.6 <dfn title="animation">Animations</dfn> are a kind of <a>timed item</a> 1.7 - that apply an animation effect to a target element or pseudo-element 1.8 - such as <code>::before</code> and <code>::first-line</code> [[!SELECT]]. 1.9 + that apply an <a>animation effect</a> to a target element or 1.10 + pseudo-element such as <code>::before</code> and 1.11 + <code>::first-line</code> [[!SELECT]]. 1.12 </p> 1.13 <section> 1.14 <h3>Calculating the time fraction</h3> 1.15 <p> 1.16 Before passing the <a>transformed time</a> of an <a>animation</a> to 1.17 - its animation effect we must convert it to a <em>time fraction</em>. 1.18 - The <dfn>time fraction</dfn> of a <a>timed item</a> is calculated 1.19 - according to the following steps: 1.20 + its <a>animation effect</a> we must convert it to a <em>time 1.21 + fraction</em>. The <dfn>time fraction</dfn> of a <a>timed item</a> is 1.22 + calculated according to the following steps: 1.23 </p> 1.24 <dl class="switch"> 1.25 <dt> 1.26 @@ -2604,716 +2605,133 @@ 1.27 </section> 1.28 </section> 1.29 1.30 + <section class="informative"> 1.31 + <h2>Overview of the animation model</h2> 1.32 + <p> 1.33 + The Web Animations <em>animation model</em> takes the <a 1.34 + title="time fraction">time fractions</a> produced by the <em>timing 1.35 + model</em> for a given <a>animation</a> and applies it as the input to 1.36 + an <a>animation effect</a> defined for the <a>animation</a>. 1.37 + The output of each <em>animation effect</em> is then combined using 1.38 + a global animation stack before being applied to the target properties 1.39 + (see <a href="#combining-animations" class="sectionRef"></a>). 1.40 + </p> 1.41 + <p> 1.42 + In order to support <a>accumulation</a> behavior the animation model 1.43 + also requires the timing model to supply an <a>animation</a>'s 1.44 + <a>current iteration</a> along with its <a>time fraction</a>. 1.45 + </p> 1.46 + </section> 1.47 + 1.48 <section> 1.49 - <h2>Animation values</h2> 1.50 - <div class="informative"> 1.51 + <h2>Animation effects</h2> 1.52 + <p> 1.53 + An <dfn>animation effect</dfn> takes a <a>time fraction</a> and uses it 1.54 + to calculate an <a>animation value</a> for its target property. 1.55 + Each <a>animation</a> may have at most one <a>animation effect</a> 1.56 + associated with it. 1.57 + </p> 1.58 + <p class="issue"> 1.59 + We will probably lift this restriction and allow animations to have 1.60 + multiple effects. 1.61 + </p> 1.62 + <p> 1.63 + Since the result of an <a>animation effect</a> is based on the 1.64 + <a>time fraction</a> it is updated whenever the timing model is <a 1.65 + title="sampling">sampled</a>. 1.66 + Note that changes to the timing model caused by using the <a 1.67 + href="#script-interface">programming interface</a> do not cause the 1.68 + animation model to be updated as described in <a 1.69 + href="#interaction-with-script" class="sectionRef"></a>. 1.70 + </p> 1.71 + <section> 1.72 + <h3>Accumulating animation values</h3> 1.73 <p> 1.74 - The Web Animations <em>animation model</em> takes the <a 1.75 - title="time fraction">time fractions</a> produced by the <em>timing 1.76 - model</em> for a given <a>Animation</a> and applies it as the input to 1.77 - the <em>animation effect</em> defined for the <a>Animation</a> object. 1.78 - The output of each <em>animation effect</em> is then combined using 1.79 - a global animation stack before being applied to the target property 1.80 - (see <a href="#combining-animations" class="sectionRef"></a>). 1.81 + <a title="animation effect">Animation effects</a> may be defined such 1.82 + that as the <a>animation</a> with which they are associated is 1.83 + repeated the <a>animation value</a> produced builds on the value 1.84 + produced by previous iterations. 1.85 + This behavior is called <dfn>accumulation</dfn>. 1.86 </p> 1.87 <p> 1.88 - The entry-point to the <em>animation model</em> is the 1.89 - <a>AnimationEffect</a> or <a>CustomAnimationEffect</a> object 1.90 - associated with each <a>Animation</a>. 1.91 - These objects describe how animation values should be calculated for 1.92 - the <a>Animation</a> for any given time. 1.93 - <a>AnimationEffect</a> serves as an abstract interface of which 1.94 - several concrete subclasses are provided. 1.95 - </p> 1.96 - </div> 1.97 - <section> 1.98 - <h3>The <code>AnimationEffect</code> interface</h3> 1.99 - <dl title="interface AnimationEffect" class="idl"> 1.100 - <dt>attribute CompositeOperation operation</dt> 1.101 + The <a>accumulation</a> behavior of an <a>animation effect</a> is 1.102 + specified by the <a>animation effect</a>'s <dfn>accumulation 1.103 + operation</dfn> property. 1.104 + The <a>accumulation operation</a> property takes one of the following 1.105 + two values. 1.106 + </p> 1.107 + <dl> 1.108 + <dt><dfn 1.109 + title="accumulation operation accumulate">accumulate</dfn></dt> 1.110 <dd> 1.111 <p> 1.112 - The operation used to composite this animation with the stack, as 1.113 - specified by one of the <a>CompositeOperation</a> enumeration 1.114 - values. 1.115 - </p> 1.116 - <p> 1.117 - This value defaults to <code>"replace"</code> 1.118 + The <a>animation value</a> for the <a>animation effect</a> is 1.119 + added to the final <a>animation value</a> of the previous 1.120 + iteration. 1.121 + </p> 1.122 + <p class="issue"> 1.123 + Should this be called <code>linear</code>? 1.124 + The only other sort of values I can imagine being used here would 1.125 + be things like <code>exponential</code> etc. 1.126 </p> 1.127 </dd> 1.128 - <dt>attribute CompositeOperation accumulateOperation</dt> 1.129 + <dt><dfn 1.130 + title="accumulation operation none">none</dfn></dt> 1.131 <dd> 1.132 - <p> 1.133 - The operation used to composite each iteration of this animation 1.134 - with the result of compositing the previous animation, as 1.135 - specified by one of the <a>CompositeOperation</a> constants 1.136 - defined in this interface. 1.137 - </p> 1.138 - <p> 1.139 - This value defaults to <code>"replace"</code>. 1.140 - </p> 1.141 - </dd> 1.142 - <dt>AnimationEffect clone ()</dt> 1.143 - <dd> 1.144 - <p> 1.145 - Creates and returns a new object of the same type as this object's 1.146 - most-derived interface such that it will produce the same output 1.147 - as this object. 1.148 - </p> 1.149 - <p class="todo"> 1.150 - We either need a more rigorous definition here or (probably 1.151 - better) a sets of steps on a per-subclass basis. 1.152 - </p> 1.153 - </dd> 1.154 - <dt>static AnimationEffect? createFromProperties ()</dt> 1.155 - <dd> 1.156 - <p> 1.157 - Creates an <a>AnimationEffect</a> representing the passed-in 1.158 - collection of properties. 1.159 - </p> 1.160 - <div class="note"> 1.161 - <p> 1.162 - Note that this method requires handling the passed in parameter 1.163 - in a manner not yet supported by Web IDL and hence this method 1.164 - is ECMAScript-specific. 1.165 - </p> 1.166 - <p> 1.167 - Since accessing the properties of an ECMAScript user object can 1.168 - have side effects, the manner in which these properties is 1.169 - accessed is important. 1.170 - In light of this consideration the following procedure has the 1.171 - following properties: 1.172 - </p> 1.173 - <ul> 1.174 - <li>Every property is read only once.</li> 1.175 - <li>Properties are read in a well-defined order.</li> 1.176 - <li>Properties corresponding to unsupported target properties or 1.177 - attributes are not read.</li> 1.178 - </ul> 1.179 - </div> 1.180 - <p> 1.181 - The interpretation of the passed-in <code>properties</code> object 1.182 - can be described in three parts. 1.183 - </p> 1.184 - <p><strong>Part 1 – Determine the set of 1.185 - animation properties</strong></p> 1.186 - <ol> 1.187 - <li>Create a list, <var>supported properties</var>, of property 1.188 - names and attribute names that can be animated by the 1.189 - implementation.</li> 1.190 - <li>Let <var>animation properties</var> be an empty sequence.</li> 1.191 - <li>Iterate through the properties of <code>properties</code>. For 1.192 - each <var>property</var> in <code>properties</code>, if 1.193 - <var>property</var> also exists in <var>supported 1.194 - properties</var> based on a case-sensitive comparison, append 1.195 - <var>property</var> to <var>animation properties</var>. 1.196 - <p class="note"> 1.197 - Whilst the iteration order for properties of an ECMAScript 1.198 - object is implementation-dependent, the order here is not 1.199 - significant to the outcome as <var>animation 1.200 - properties</var> will be sorted before being iterated over. 1.201 - </p> 1.202 - <p class="issue"> 1.203 - How do we handle <code>operation</code> and 1.204 - <code>compositeOperation</code>? We'd like to be able to 1.205 - list them in the same property bag but that would mean we 1.206 - could never animate properties of the same name. 1.207 - </p> 1.208 - </li> 1.209 - </ol> 1.210 - <p><strong>Part 2 – Create the <a>AnimationEffect</a> 1.211 - objects</strong></p> 1.212 - <p> 1.213 - The <a>AnimationEffect</a> object produced depends on the length 1.214 - of <var>animation properties</var> as follows: 1.215 - </p> 1.216 - <dl class="switch"> 1.217 - <dt>If <var>animation properties</var> is of zero length,</dt> 1.218 - <dd> 1.219 - return <code>null</code>. 1.220 - <div class="note"> 1.221 - <p> 1.222 - This behavior of returning <code>null</code> allows 1.223 - alternative animation effects to be provided based on the 1.224 - capabilities of the user agent as follows: 1.225 - </p> 1.226 - <pre class="example sh_javascript"> 1.227 -elem.animate( 1.228 - AnimationEffect.createFromProperties({ transform: 'translate(-100px)' }) || 1.229 - AnimationEffect.createFromProperties({ top: '-100px' }), 1.230 - 3); 1.231 - </pre> 1.232 - </div> 1.233 - </dd> 1.234 - <dt>If <var>animation properties</var> has only one element,</dt> 1.235 - <dd> 1.236 - <ol> 1.237 - <li>Let <var>name</var> be the value of the element 1.238 - in <var>animation properties</var>.</li> 1.239 - <li>Let <var>value</var> be the value of 1.240 - <code>properties.<var>name</var></code>.</li> 1.241 - <li>Return a new <a>KeyframeAnimationEffect</a> object 1.242 - according to the steps in part 3 below based on 1.243 - <var>name</var> and <var>value</var>.</li> 1.244 - </ol> 1.245 - </dd> 1.246 - <dt>Otherwise,</dt> 1.247 - <dd> 1.248 - <ol> 1.249 - <li>Let <var>group</var> be a newly constructed 1.250 - <a>GroupedAnimationEffect</a>.</li> 1.251 - <li>Sort <var>animation properties</var> lexicographically by 1.252 - the Unicode codepoints that define each property 1.253 - name.</li> 1.254 - <li>For user agents that support both a prefixed and an 1.255 - unprefixed version of some CSS properties, remove all 1.256 - prefixed properties from <var>animation properties</var> 1.257 - where the corresponding unprefixed version is also 1.258 - present.</li> 1.259 - <li>Iterate through <var>animation properties</var>. For each 1.260 - <var>name</var> in <var>animation properties</var>: 1.261 - <ol> 1.262 - <li>Let <var>value</var> be the value of 1.263 - <code>properties.<var>name</var></code>.</li> 1.264 - <li>Create a new <a>KeyframeAnimationEffect</a>, 1.265 - <var>effect</var> object according to the steps in 1.266 - part 3 below based on <var>name</var> and 1.267 - <var>value</var>.</li> 1.268 - <li>Append <var>effect</var> to <var>group</var>. 1.269 - </ol> 1.270 - </li> 1.271 - <li>Return <var>group</var>. 1.272 - </ol> 1.273 - </dd> 1.274 - </dl> 1.275 - <p><strong>Part 3 – Create each 1.276 - <a>KeyframeAnimationEffect</a> object</strong></p> 1.277 - <p> 1.278 - Based on a given <var>name</var> and <var>value</var>, a new 1.279 - <a>KeyframeAnimationEffect</a> is created as follows: 1.280 - </p> 1.281 - <dl class="switch"> 1.282 - <dt>If <var>value</var> is not of type <code>(DOMString or 1.283 - sequence<(<a>KeyframeDictionary</a> or 1.284 - DOMString)>)</code>,</dt> 1.285 - <dd> 1.286 - Throw a <code>TypeError</code> as defined by [[!ECMA-262]]. 1.287 - </dd> 1.288 - <dt>Otherwise,</dt> 1.289 - <dd> 1.290 - Construct a new <a>KeyframeAnimationEffect</a> by calling 1.291 - <code>KeyframeAnimationEffect(<var>name</var>, 1.292 - <var>value</var>)</code>. 1.293 - </dd> 1.294 - </dl> 1.295 - <dl class="parameters"> 1.296 - <dt>object properties</dt> 1.297 - <dd> 1.298 - An object whose object properties represent the CSS properties 1.299 - or element attributes to be animated. 1.300 - The values corresponding to these properties are the animation 1.301 - values to be applied as described above. 1.302 - </dd> 1.303 - </dl> 1.304 + The <a>animation value</a> for the <a>animation effect</a> is 1.305 + calculated independently of the <a>current iteration</a>. 1.306 </dd> 1.307 </dl> 1.308 - <div class="annotation"> 1.309 - In future, we may expose <code>any sample (double? timeFraction, 1.310 - double currentIteration, AnimationTarget? target, any 1.311 - underlyingValue)</code> so that the animation effects can be driven 1.312 - apart from the timing model. 1.313 - Also, doing so would allow us to do real native custom animation 1.314 - effects if we decide to go in that direction 1.315 - (see annotation in <a href="#custom-animation-effects" 1.316 - class="sectionRef"></a>). 1.317 - </div> 1.318 + <p class="issue"> 1.319 + Does accumulation actually make sense for path animations or should we 1.320 + define this as a property of key frame animations effects only? 1.321 + </p> 1.322 </section> 1.323 <section> 1.324 - <h3>The <code>CompositeOperation</code> enumeration</h3> 1.325 - <dl title="enum CompositeOperation" class="idl"> 1.326 - <dt>replace</dt> 1.327 + <h3>Calculating the animation value</h3> 1.328 + <p> 1.329 + The <a>animation value</a> of an <a>animation effect</a> for a given 1.330 + <a>time fraction</a> and <a>current iteration</a> is produced by first 1.331 + calculating the value independently of any <a>accumulation</a> 1.332 + behavior. 1.333 + This initial value is called the <dfn>iteration value</dfn> and is 1.334 + defined for each concrete type of <a>animation effect</a>. 1.335 + </p> 1.336 + <p> 1.337 + Having calculated an <a>iteration value</a> for an <a>animation 1.338 + effect</a>, the <dfn>animation value</dfn> is as follows: 1.339 + </p> 1.340 + <dl class="switch"> 1.341 + <dt>If <a>accumulation operation</a> is <a 1.342 + title="accumulation operation none">none</a>,</dt> 1.343 <dd> 1.344 - The animation should replace the value it is composited with. 1.345 + Return the <a>iteration value</a>. 1.346 </dd> 1.347 - <dt>accumulate</dt> 1.348 + <dt>Otherwise,</dt> 1.349 <dd> 1.350 - The animation should add to the value it is composited with. 1.351 - The meaning of addition is dependent on the type of animation. 1.352 - </dd> 1.353 - <dt>merge</dt> 1.354 - <dd> 1.355 - The animation should merge with the value it is composited with. 1.356 - The meaning of merge is dependent on the type of animation. 1.357 - The duration of the merge is the calculated animation duration 1.358 - of the <code>AnimationTemplate</code> containing this 1.359 - <code>AnimationEffect</code>. 1.360 + <ol> 1.361 + <li>Let <var>last value</var> be the result of evaluating 1.362 + the <a>iteration value</a> of the <a>animation effect</a> 1.363 + with a <a>time fraction</a> of 1.</li> 1.364 + <li>Let <var>previous iteration value</var> be the result of 1.365 + adding <var>last value</var> to itself <a>current 1.366 + iteration</a> times. 1.367 + <li>Return the result of adding together <var>previous iteration 1.368 + value</var> and the current <a>iteration value</a> of the 1.369 + <a>animation value</a> (that is, the <a>iteration value</a> 1.370 + calculated for the current <a>time fraction</a>).</li> 1.371 + </ol> 1.372 </dd> 1.373 </dl> 1.374 - </section> 1.375 - <section> 1.376 - <h3>The <code>KeyframeAnimationEffect</code> interface</h3> 1.377 - <dl title="interface KeyframeAnimationEffect : AnimationEffect" 1.378 - class="idl"> 1.379 - <dt>Constructor (DOMString property, 1.380 - (DOMString or sequence<(KeyframeDictionary or DOMString)>) frames, 1.381 - optional CompositeOperation operation = "replace", 1.382 - optional CompositeOperation compositeOperation = "replace")</dt> 1.383 - <dd> 1.384 - <p> 1.385 - Creates a new <a>KeyframeAnimationEffect</a> object for the 1.386 - specified property from the given list of keyframes. 1.387 - </p> 1.388 - <p> 1.389 - The list of keyframes may be a sequence of 1.390 - <a>KeyframeDictionary</a> dictionaries, a sequence of 1.391 - <code>DOMString</code>s, a combination of both, or 1.392 - a single <code>DOMString</code>. 1.393 - </p> 1.394 - <p> 1.395 - <code>DOMString</code>s are used to create keyframes with an 1.396 - offset of 1. 1.397 - When the list of keyframes is a sequence consisting entirely of 1.398 - <code>DOMString</code>s the offsets of the newly created 1.399 - <a>Keyframe</a>s are distributed evenly from 0 to 1. 1.400 - </p> 1.401 - <p> 1.402 - The <var>property</var>, <var>operation</var> and 1.403 - <var>compositeOperation</var> arguments are assigned to the 1.404 - attributes of the same names. 1.405 - </p> 1.406 - <p> 1.407 - The <var>frames</var> argument is processed as follows: 1.408 - </p> 1.409 - <ol> 1.410 - <li>Let <var>effect</var> be the 1.411 - <a>KeyframeAnimationEffect</a> currently under construction. 1.412 - </li> 1.413 - <li> 1.414 - <p> 1.415 - The processing of <var>frames</var> depends on its type as 1.416 - follows: 1.417 - </p> 1.418 - <dl class="switch"> 1.419 - <dt>If <var>frames</var> is a <code>DOMString</code>,</dt> 1.420 - <dd> 1.421 - <ol> 1.422 - <li> 1.423 - Let <var>frame</var> be a new <a>Keyframe</a> 1.424 - constructed from a <a>KeyframeDictionary</a> whose 1.425 - <code>value</code> member is set to 1.426 - <var>frames</var> and whose other members are set 1.427 - to their default values. 1.428 - </li> 1.429 - <li> 1.430 - Call 1.431 - <code><var>effect</var>.frames.add(<var>frame</var>)</code>. 1.432 - </li> 1.433 - </ol> 1.434 - </dd> 1.435 - <dt>If <var>frames</var> is a sequence of <code>(DOMString 1.436 - or <a>KeyframeDictionary</a>)</code>,</dt> 1.437 - <dd> 1.438 - <ol> 1.439 - <li>Set a flag <var>all strings</var> to 1.440 - <code>true</code>.</li> 1.441 - <li> 1.442 - For each <var>item</var> in <var>frames</var>: 1.443 - <ol> 1.444 - <li> 1.445 - <dl class="switch"> 1.446 - <dt>If <var>item</var> is 1.447 - a <code>DOMString</code>,</dt> 1.448 - <dd> 1.449 - Let <var>frame</var> be a new <a>Keyframe</a> 1.450 - constructed from a <a>KeyframeDictionary</a> 1.451 - whose <code>value</code> member is set to 1.452 - <var>item</var> and whose other members are 1.453 - set to their default values. 1.454 - </dd> 1.455 - <dt>Otherwise (<var>item</var> is 1.456 - a <a>KeyframeDictionary</a>),</dt> 1.457 - <dd> 1.458 - <ol> 1.459 - <li> 1.460 - Let <var>frame</var> be a new 1.461 - <a>Keyframe</a> constructed by calling 1.462 - <code>Keyframe(<var>item</var>)</code>. 1.463 - </li> 1.464 - <li> 1.465 - Set <var>all strings</var> to 1.466 - <code>false</code>. 1.467 - </li> 1.468 - </ol> 1.469 - </dd> 1.470 - </dl> 1.471 - </li> 1.472 - <li> 1.473 - Call 1.474 - <code><var>effect</var>.frames.add(<var>frame</var>)</code>. 1.475 - </li> 1.476 - </ol> 1.477 - </li> 1.478 - <li>If flag <var>all strings</var> is 1.479 - <code>true</code> call 1.480 - <code><var>effect</var>.frames.distribute()</code>. 1.481 - </li> 1.482 - </ol> 1.483 - </dd> 1.484 - </dl> 1.485 - </li> 1.486 - </ol> 1.487 - </dd> 1.488 - <dt>attribute DOMString property</dt> 1.489 - <dd> 1.490 - The name of the target property or attribute. 1.491 - </dd> 1.492 - <dt>readonly attribute KeyframeList frames</dt> 1.493 - <dd> 1.494 - The series of values that make up this effect sorted by their 1.495 - offset within the iteration duration of the animation. 1.496 - </dd> 1.497 - </dl> 1.498 - </section> 1.499 - <section> 1.500 - <h3>The <code>KeyframeList</code> interface</h3> 1.501 - <p> 1.502 - The <a>KeyframeList</a> object is a collection of <a>Keyframe</a> 1.503 - objects sorted by the offset of each <a>Keyframe</a>. 1.504 - </p> 1.505 - <dl title="interface KeyframeList" class="idl"> 1.506 - <dt>readonly attribute unsigned long length</dt> 1.507 - <dd> 1.508 - The number of frames in the list. 1.509 - </dd> 1.510 - <dt>void clear ()</dt> 1.511 - <dd> 1.512 - Removes all frames from this list. 1.513 - </dd> 1.514 - <dt>getter Keyframe? (unsigned long index)</dt> 1.515 - <dd> 1.516 - Returns the frame at <code>index</code> if it exists or 1.517 - <code>null</code> otherwise. 1.518 - </dd> 1.519 - <dt>Keyframe add((Keyframe or KeyframeDictionary) frame)</dt> 1.520 - <dd> 1.521 - <p> 1.522 - Adds <var>frame</var> to the list such that the list remains 1.523 - sorted by the offset of the frames. 1.524 - </p> 1.525 - <p> 1.526 - If <var>frame</var> is of type <a>KeyframeDictionary</a> then 1.527 - a <a>Keyframe</a> object is first constructed by calling 1.528 - <code>Keyframe(<var>frame</var>)</code> before adding the 1.529 - newly constructed <a>Keyframe</a> to the list. 1.530 - </p> 1.531 - <p> 1.532 - If there already exists a frame in this list with offset 1.533 - <code><var>frame</var>.offset</code>, the newly added 1.534 - <var>frame</var> will appear in the list <em>after</em> the 1.535 - already existing frames in the list with the same offset. 1.536 - </p> 1.537 - <p> 1.538 - If <var>frame</var> is already part of another <a>KeyframeList</a> 1.539 - it is first removed from that list before being added to this 1.540 - list. 1.541 - </p> 1.542 - <p> 1.543 - Exceptions: 1.544 - </p> 1.545 - <dl class="exceptions"> 1.546 - <dt>DOMException of type <code>IndexSizeError</code></dt> 1.547 - <dd> 1.548 - Raised if <var>frame</var> is a <a>KeyframeDictionary</a> whose 1.549 - offset is outside the range [0,1] or missing. 1.550 - </dd> 1.551 - </dl> 1.552 - </dd> 1.553 - <dt>Keyframe? remove(unsigned long index)</dt> 1.554 - <dd> 1.555 - Removes the frame at position <var>index</var> and returns it. 1.556 - If index is outside the range [0, length), then <code>null</code> is 1.557 - returned. 1.558 - </dd> 1.559 - <dt>long indexOf(Keyframe frame)</dt> 1.560 - <dd> 1.561 - Returns the index of <var>frame</var> within the list. If 1.562 - <var>frame</var> is not a member of the list, returns 1.563 - <code>-1</code>. 1.564 - </dd> 1.565 - <dt>KeyframeList distribute()</dt> 1.566 - <dd> 1.567 - <p> 1.568 - Adjusts the offsets of the frames in the list such that the 1.569 - offsets are spaced equidistantly whilst maintaining their current 1.570 - order and such that the first frame (when there are multiple 1.571 - frames) has offset 0 and the last frame (if any) has offset 1. 1.572 - </p> 1.573 - <p> 1.574 - For <var>frame</var> at position <var>i</var> in the list where 1.575 - 0 ≤ <var>i</var> < <code>length</code>, an offset will be 1.576 - assigned equal to <code>i / (length - 1)</code> unless 1.577 - <code>length</code> is 1 in which case it will be given offset 1.578 - 1. 1.579 - </p> 1.580 - <p> 1.581 - After applying the changes, this list is returned. 1.582 - </p> 1.583 - </dd> 1.584 - </dl> 1.585 - <div class="annotation"> 1.586 - <p> 1.587 - The following changes for making keyframes easier to work with in 1.588 - future have been proposed: 1.589 - </p> 1.590 - <pre class="example sh_javascript"> 1.591 -// Currently you have to do this 1.592 -effect.frames.add({ property: 'left', offset: 0.3, value: '100px' }); 1.593 - 1.594 -// It would be nice if you could also do this 1.595 -effect.frames.add(0.3, 'left', '100px'); 1.596 - 1.597 -// Also, fetching by offset would be good 1.598 - 1.599 -// Returns the last frame with offset 0.3 if there is one. 1.600 -// If there is none, does the interpolation and returns a new frame? 1.601 -var frame = effect.frames['0.3']; 1.602 - </pre> 1.603 - </div> 1.604 - </section> 1.605 - <section> 1.606 - <h3>The <code>Keyframe</code> interface</h3> 1.607 - <p> 1.608 - A <a>Keyframe</a> represents a moment within an animation that has 1.609 - a specified value to be applied to the target property or attribute. 1.610 - In between such moments values may be interpolated or filled based on 1.611 - the <a>TimingFunction</a> specified on the <a>TimedItem</a> where the 1.612 - <a>Keyframe</a> is used, or on the previous <a>Keyframe</a>. 1.613 - </p> 1.614 - <div class="issue"> 1.615 - <p> 1.616 - Currently a <a>Keyframe</a> can only target a single property which 1.617 - is defined on the <a>KeyframeAnimationEffect</a>. 1.618 - This is different to CSS. 1.619 - Is this something we want to change? 1.620 - It would complicate the API, of course, but is it worth it? 1.621 - </p> 1.622 - </div> 1.623 - <p> 1.624 - <dl title="interface Keyframe" class="idl"> 1.625 - <dt>Constructor (KeyframeDictionary dictionary)</dt> 1.626 - <dd> 1.627 - <p> 1.628 - Creates a new <a>Keyframe</a> object using the parameters 1.629 - specified in <var>dictionary</var>. 1.630 - </p> 1.631 - <p> 1.632 - <code><var>dictionary</var>.offset</code> is clamped to the 1.633 - range [0, 1] before setting. 1.634 - </p> 1.635 - </dd> 1.636 - <dt>attribute DOMString value</dt> 1.637 - <dd> 1.638 - The value to assign to the target attribute or property at the 1.639 - given offset. 1.640 - </dd> 1.641 - <dt>attribute double offset</dt> 1.642 - <dd> 1.643 - <p> 1.644 - A value between 0 and 1 inclusive representing the offset 1.645 - within the iteration duration of the animation where this value 1.646 - should appear. 1.647 - </p> 1.648 - <p> 1.649 - If this keyframe belongs to a <a>KeyframeList</a>, changes to 1.650 - this value cause the <a>KeyframeList</a> to be immediately 1.651 - re-sorted using a stable sort such that all children are ordered 1.652 - by their offset but children with identical offsets retain their 1.653 - relative position in the list. 1.654 - </p> 1.655 - <p> 1.656 - Exceptions: 1.657 - </p> 1.658 - <dl class="exceptions"> 1.659 - <dt>DOMException of type <code>IndexSizeError</code></dt> 1.660 - <dd> 1.661 - Raised on setting a value outside the range [0,1]. 1.662 - </dd> 1.663 - </dl> 1.664 - </dd> 1.665 - <dt>attribute TimingFunction? timingFunction</dt> 1.666 - <dd> 1.667 - <p> 1.668 - The timing function to apply between this keyframe and the 1.669 - next keyframe in any <a>KeyframeList</a> in which this object 1.670 - appears. 1.671 - </p> 1.672 - <p> 1.673 - May be <code>null</code> in which case linear interpolation will 1.674 - be used. 1.675 - </p> 1.676 - </dd> 1.677 - </dl> 1.678 - </p> 1.679 - </section> 1.680 - <section> 1.681 - <h3>The <code>KeyframeDictionary</code> dictionary</h3> 1.682 - <p> 1.683 - To simplify creation of <a>Keyframe</a> objects 1.684 - a <code>KeyframeDictionary</code> can be used. 1.685 - </p> 1.686 - <p> 1.687 - The members of the dictionary correspond to attributes in the 1.688 - <a>Keyframe</a> interface which provides a more complete description 1.689 - of their meaning and usage. 1.690 - </p> 1.691 - <dl title="dictionary KeyframeDictionary" class="idl"> 1.692 - <dt>DOMString value = ""</dt> 1.693 - <dd> 1.694 - The value to assign to the target attribute or property at the given 1.695 - offset. 1.696 - </dd> 1.697 - <dt>double offset = 1</dt> 1.698 - <dd> 1.699 - A value between 0 and 1 (inclusive) representing the offset within 1.700 - the iteration duration of the animation where this value should 1.701 - appear. 1.702 - </dd> 1.703 - <dt>TimingFunction? timingFunction = null</dt> 1.704 - <dd> 1.705 - The timing function to apply between this keyframe and the 1.706 - next keyframe in any <a>KeyframeList</a> in which this object 1.707 - appears. 1.708 - </dd> 1.709 - </dl> 1.710 - </section> 1.711 - <section> 1.712 - <h3>The <code>PathAnimationEffect</code> interface</h3> 1.713 - <dl title="[Constructor] interface PathAnimationEffect 1.714 - : AnimationEffect" class="idl"> 1.715 - <dt>attribute SVGPathSegList segments</dt> 1.716 - <dd> 1.717 - The list of segments that make up this path. 1.718 - </dd> 1.719 - <dt>attribute boolean rotate</dt> 1.720 - <dd> 1.721 - True if objects animating along this path should be rotated 1.722 - such that their positive x axis is aligned with the direction of 1.723 - movement along the path. 1.724 - </dd> 1.725 - </dl> 1.726 - </section> 1.727 - <section> 1.728 - <h3>The <code>GroupedAnimationEffect</code> interface</h3> 1.729 - <p> 1.730 - The <code>GroupedAnimationEffect</code> interface represents a 1.731 - set of animation effects that share the same 1.732 - <code>AnimationTemplate</code> parent. 1.733 + <p class="issue"> 1.734 + This definition relies on the final value of <a 1.735 + title="timing function">timing functions</a> being 1. 1.736 </p> 1.737 <p class="todo"> 1.738 - If the group contains multiple effects that target the same property 1.739 - does order in the group matter? If so, we need to add a means for 1.740 - re-ordering the group other than popping and pushing. For example, 1.741 - <code>insertBefore</code>. 1.742 - </p> 1.743 - <dl title="interface GroupedAnimationEffect : AnimationEffect" 1.744 - class="idl"> 1.745 - <dt>Constructor (object properties)</dt> 1.746 - <dd> 1.747 - <p class="todo"> 1.748 - TBD whilst we decide whether we need this interface or whether we 1.749 - can merge it with <a>KeyframeAnimationEffect</a> somehow. 1.750 - </p> 1.751 - </dd> 1.752 - <dt>readonly attribute unsigned long length</dt> 1.753 - <dd> 1.754 - The number of animation effects in the group. 1.755 - </dd> 1.756 - <dt>void clear()</dt> 1.757 - <dd> 1.758 - Removes all effects from this group. 1.759 - </dd> 1.760 - <dt>getter AnimationEffect? (unsigned long index)</dt> 1.761 - <dd> 1.762 - Returns the effect at <var>index</var> if it exists, or 1.763 - <code>null</code> otherwise. 1.764 - </dd> 1.765 - <dt>AnimationEffect add(AnimationEffect effect)</dt> 1.766 - <dd> 1.767 - <p> 1.768 - Appends <code>effect</code> to the end of the group such that 1.769 - <code>group.indexOf(<var>effect</var>)</code> equals 1.770 - <code>group.length - 1</code>. 1.771 - </p> 1.772 - <p class="todo"> 1.773 - I'm assuming that <a>AnimationEffect</a>s can be shared amongst 1.774 - animations and groups. 1.775 - Or does <var>effect</var> need to be removed from any previous 1.776 - <a>AnimationEffect</a>s or <a>Animation</a>s first? 1.777 - </p> 1.778 - </dd> 1.779 - <dt>AnimationEffect? remove(unsigned long index)</dt> 1.780 - <dd> 1.781 - Removes the effect at <code>index</code> and returns it. If 1.782 - <var>index</var> is outside the range [0, <code>length</code>), then 1.783 - <code>null</code> is returned. 1.784 - </dd> 1.785 - <dt>long indexOf(AnimationEffect effect)</dt> 1.786 - <dd> 1.787 - Returns the index of <var>effect</var> within the group. 1.788 - If <var>effect</var> is not a member of the group, returns 1.789 - <code>-1</code>. 1.790 - </dd> 1.791 - </dl> 1.792 - </section> 1.793 - <section> 1.794 - <h3>Calculating animation values</h3> 1.795 - <div class="todo"> 1.796 - This section needs more detail on when sampling is done. 1.797 - It also needs to be specified that an <a>Animation</a> with 1.798 - a <code>null</code> <a>AnimationEffect</a> still fires events. 1.799 - </div> 1.800 - <section> 1.801 - <h4>Calculating the animation value from an iteration value</h4> 1.802 - <p> 1.803 - If the <a>current iteration</a> is zero, or the 1.804 - <var>accumulateOperation</var> is 1.805 - <code>"replace"</code>, then the 1.806 - <var>animation value</var> is simply the iteration value, as 1.807 - defined below. 1.808 - </p> 1.809 - <p> 1.810 - When the animation time equals the iteration duration for the 1.811 - first time for an animation, the current 1.812 - <var>animation value</var> should be retained as the 1.813 - <var>end value</var> for the animation. 1.814 - </p> 1.815 - <p class="todo"> 1.816 - Need to revise this definition since we can't assume the time at 1.817 - the end of the first iteration will be visited (we might be 1.818 - playing backwards, or have a <var>iteration start</var> greater 1.819 - than 1). 1.820 - </p> 1.821 - <p> 1.822 - If the <a>current iteration</a> is not zero and the 1.823 - <var>accumulateOperation</var> is 1.824 - <code>"accumulate"</code> then the 1.825 - <var>animation value</var> is the <var>end value</var> accumulated 1.826 - <a>current iteration</a> times, with the 1.827 - <var>iteration value</var> accumulated on top. 1.828 - </p> 1.829 - <p> 1.830 - If the <a>current iteration</a> is not zero and the 1.831 - <var>accumulateOperation</var> is 1.832 - <code>"merge"</code> then the 1.833 - <var>animation balue</var> is the <var>end value</var> merged 1.834 - with the <var>iteration value</var>, with an interpolation 1.835 - parameter equal to the current <var>time fraction</var> 1.836 - </p> 1.837 - <p class="todo"> 1.838 - Need to review the following algorithms to check they still make 1.839 - sense now that the iteration fraction is not necessarily in the 1.840 - range [0, 1]. 1.841 - </p> 1.842 - </section> 1.843 + This definition relies on the concept of addition being defined for 1.844 + all animation effects. 1.845 + Need to point to where this is defined. 1.846 + </p> 1.847 <section> 1.848 <h4>Calculating the iteration value for a 1.849 <code>KeyframeAnimationEffect</code></h4> 1.850 @@ -5483,6 +4901,650 @@ 1.851 </div> 1.852 </section> 1.853 <section> 1.854 + <h3>The <code>AnimationEffect</code> interface</h3> 1.855 + <p> 1.856 + <a title="animation effect">Animation effects</a> are represented by 1.857 + the <code>AnimationEffect</code> interface. 1.858 + <a>AnimationEffect</a> is an abstract interface of which several 1.859 + concrete subinterfaces are provided. 1.860 + </p> 1.861 + <dl title="interface AnimationEffect" class="idl"> 1.862 + <dt>attribute CompositeOperation operation</dt> 1.863 + <dd> 1.864 + <p> 1.865 + The operation used to composite this animation with the stack, as 1.866 + specified by one of the <a>CompositeOperation</a> enumeration 1.867 + values. 1.868 + </p> 1.869 + <p> 1.870 + This value defaults to <code>"replace"</code> 1.871 + </p> 1.872 + </dd> 1.873 + <dt>attribute CompositeOperation accumulateOperation</dt> 1.874 + <dd> 1.875 + <p> 1.876 + The operation used to composite each iteration of this animation 1.877 + with the result of compositing the previous animation, as 1.878 + specified by one of the <a>CompositeOperation</a> constants 1.879 + defined in this interface. 1.880 + </p> 1.881 + <p> 1.882 + This value defaults to <code>"replace"</code>. 1.883 + </p> 1.884 + </dd> 1.885 + <dt>AnimationEffect clone ()</dt> 1.886 + <dd> 1.887 + <p> 1.888 + Creates and returns a new object of the same type as this object's 1.889 + most-derived interface such that it will produce the same output 1.890 + as this object. 1.891 + </p> 1.892 + <p class="todo"> 1.893 + We either need a more rigorous definition here or (probably 1.894 + better) a sets of steps on a per-subclass basis. 1.895 + </p> 1.896 + </dd> 1.897 + <dt>static AnimationEffect? createFromProperties ()</dt> 1.898 + <dd> 1.899 + <p> 1.900 + Creates an <a>AnimationEffect</a> representing the passed-in 1.901 + collection of properties. 1.902 + </p> 1.903 + <div class="note"> 1.904 + <p> 1.905 + Note that this method requires handling the passed in parameter 1.906 + in a manner not yet supported by Web IDL and hence this method 1.907 + is ECMAScript-specific. 1.908 + </p> 1.909 + <p> 1.910 + Since accessing the properties of an ECMAScript user object can 1.911 + have side effects, the manner in which these properties is 1.912 + accessed is important. 1.913 + In light of this consideration the following procedure has the 1.914 + following properties: 1.915 + </p> 1.916 + <ul> 1.917 + <li>Every property is read only once.</li> 1.918 + <li>Properties are read in a well-defined order.</li> 1.919 + <li>Properties corresponding to unsupported target properties or 1.920 + attributes are not read.</li> 1.921 + </ul> 1.922 + </div> 1.923 + <p> 1.924 + The interpretation of the passed-in <code>properties</code> object 1.925 + can be described in three parts. 1.926 + </p> 1.927 + <p><strong>Part 1 – Determine the set of 1.928 + animation properties</strong></p> 1.929 + <ol> 1.930 + <li>Create a list, <var>supported properties</var>, of property 1.931 + names and attribute names that can be animated by the 1.932 + implementation.</li> 1.933 + <li>Let <var>animation properties</var> be an empty sequence.</li> 1.934 + <li>Iterate through the properties of <code>properties</code>. For 1.935 + each <var>property</var> in <code>properties</code>, if 1.936 + <var>property</var> also exists in <var>supported 1.937 + properties</var> based on a case-sensitive comparison, append 1.938 + <var>property</var> to <var>animation properties</var>. 1.939 + <p class="note"> 1.940 + Whilst the iteration order for properties of an ECMAScript 1.941 + object is implementation-dependent, the order here is not 1.942 + significant to the outcome as <var>animation 1.943 + properties</var> will be sorted before being iterated over. 1.944 + </p> 1.945 + <p class="issue"> 1.946 + How do we handle <code>operation</code> and 1.947 + <code>compositeOperation</code>? We'd like to be able to 1.948 + list them in the same property bag but that would mean we 1.949 + could never animate properties of the same name. 1.950 + </p> 1.951 + </li> 1.952 + </ol> 1.953 + <p><strong>Part 2 – Create the <a>AnimationEffect</a> 1.954 + objects</strong></p> 1.955 + <p> 1.956 + The <a>AnimationEffect</a> object produced depends on the length 1.957 + of <var>animation properties</var> as follows: 1.958 + </p> 1.959 + <dl class="switch"> 1.960 + <dt>If <var>animation properties</var> is of zero length,</dt> 1.961 + <dd> 1.962 + return <code>null</code>. 1.963 + <div class="note"> 1.964 + <p> 1.965 + This behavior of returning <code>null</code> allows 1.966 + alternative animation effects to be provided based on the 1.967 + capabilities of the user agent as follows: 1.968 + </p> 1.969 + <pre class="example sh_javascript"> 1.970 +elem.animate( 1.971 + AnimationEffect.createFromProperties({ transform: 'translate(-100px)' }) || 1.972 + AnimationEffect.createFromProperties({ top: '-100px' }), 1.973 + 3); 1.974 + </pre> 1.975 + </div> 1.976 + </dd> 1.977 + <dt>If <var>animation properties</var> has only one element,</dt> 1.978 + <dd> 1.979 + <ol> 1.980 + <li>Let <var>name</var> be the value of the element 1.981 + in <var>animation properties</var>.</li> 1.982 + <li>Let <var>value</var> be the value of 1.983 + <code>properties.<var>name</var></code>.</li> 1.984 + <li>Return a new <a>KeyframeAnimationEffect</a> object 1.985 + according to the steps in part 3 below based on 1.986 + <var>name</var> and <var>value</var>.</li> 1.987 + </ol> 1.988 + </dd> 1.989 + <dt>Otherwise,</dt> 1.990 + <dd> 1.991 + <ol> 1.992 + <li>Let <var>group</var> be a newly constructed 1.993 + <a>GroupedAnimationEffect</a>.</li> 1.994 + <li>Sort <var>animation properties</var> lexicographically by 1.995 + the Unicode codepoints that define each property 1.996 + name.</li> 1.997 + <li>For user agents that support both a prefixed and an 1.998 + unprefixed version of some CSS properties, remove all 1.999 + prefixed properties from <var>animation properties</var> 1.1000 + where the corresponding unprefixed version is also 1.1001 + present.</li> 1.1002 + <li>Iterate through <var>animation properties</var>. For each 1.1003 + <var>name</var> in <var>animation properties</var>: 1.1004 + <ol> 1.1005 + <li>Let <var>value</var> be the value of 1.1006 + <code>properties.<var>name</var></code>.</li> 1.1007 + <li>Create a new <a>KeyframeAnimationEffect</a>, 1.1008 + <var>effect</var> object according to the steps in 1.1009 + part 3 below based on <var>name</var> and 1.1010 + <var>value</var>.</li> 1.1011 + <li>Append <var>effect</var> to <var>group</var>. 1.1012 + </ol> 1.1013 + </li> 1.1014 + <li>Return <var>group</var>. 1.1015 + </ol> 1.1016 + </dd> 1.1017 + </dl> 1.1018 + <p><strong>Part 3 – Create each 1.1019 + <a>KeyframeAnimationEffect</a> object</strong></p> 1.1020 + <p> 1.1021 + Based on a given <var>name</var> and <var>value</var>, a new 1.1022 + <a>KeyframeAnimationEffect</a> is created as follows: 1.1023 + </p> 1.1024 + <dl class="switch"> 1.1025 + <dt>If <var>value</var> is not of type <code>(DOMString or 1.1026 + sequence<(<a>KeyframeDictionary</a> or 1.1027 + DOMString)>)</code>,</dt> 1.1028 + <dd> 1.1029 + Throw a <code>TypeError</code> as defined by [[!ECMA-262]]. 1.1030 + </dd> 1.1031 + <dt>Otherwise,</dt> 1.1032 + <dd> 1.1033 + Construct a new <a>KeyframeAnimationEffect</a> by calling 1.1034 + <code>KeyframeAnimationEffect(<var>name</var>, 1.1035 + <var>value</var>)</code>. 1.1036 + </dd> 1.1037 + </dl> 1.1038 + <dl class="parameters"> 1.1039 + <dt>object properties</dt> 1.1040 + <dd> 1.1041 + An object whose object properties represent the CSS properties 1.1042 + or element attributes to be animated. 1.1043 + The values corresponding to these properties are the animation 1.1044 + values to be applied as described above. 1.1045 + </dd> 1.1046 + </dl> 1.1047 + </dd> 1.1048 + </dl> 1.1049 + <div class="annotation"> 1.1050 + In future, we may expose <code>any sample (double? timeFraction, 1.1051 + double currentIteration, AnimationTarget? target, any 1.1052 + underlyingValue)</code> so that the animation effects can be driven 1.1053 + apart from the timing model. 1.1054 + Also, doing so would allow us to do real native custom animation 1.1055 + effects if we decide to go in that direction 1.1056 + (see annotation in <a href="#custom-animation-effects" 1.1057 + class="sectionRef"></a>). 1.1058 + </div> 1.1059 + </section> 1.1060 + <section> 1.1061 + <h3>The <code>CompositeOperation</code> enumeration</h3> 1.1062 + <dl title="enum CompositeOperation" class="idl"> 1.1063 + <dt>replace</dt> 1.1064 + <dd> 1.1065 + The animation should replace the value it is composited with. 1.1066 + </dd> 1.1067 + <dt>accumulate</dt> 1.1068 + <dd> 1.1069 + The animation should add to the value it is composited with. 1.1070 + The meaning of addition is dependent on the type of animation. 1.1071 + </dd> 1.1072 + <dt>merge</dt> 1.1073 + <dd> 1.1074 + The animation should merge with the value it is composited with. 1.1075 + The meaning of merge is dependent on the type of animation. 1.1076 + The duration of the merge is the calculated animation duration 1.1077 + of the <code>AnimationTemplate</code> containing this 1.1078 + <code>AnimationEffect</code>. 1.1079 + </dd> 1.1080 + </dl> 1.1081 + </section> 1.1082 + <section> 1.1083 + <h3>The <code>KeyframeAnimationEffect</code> interface</h3> 1.1084 + <dl title="interface KeyframeAnimationEffect : AnimationEffect" 1.1085 + class="idl"> 1.1086 + <dt>Constructor (DOMString property, 1.1087 + (DOMString or sequence<(KeyframeDictionary or DOMString)>) frames, 1.1088 + optional CompositeOperation operation = "replace", 1.1089 + optional CompositeOperation compositeOperation = "replace")</dt> 1.1090 + <dd> 1.1091 + <p> 1.1092 + Creates a new <a>KeyframeAnimationEffect</a> object for the 1.1093 + specified property from the given list of keyframes. 1.1094 + </p> 1.1095 + <p> 1.1096 + The list of keyframes may be a sequence of 1.1097 + <a>KeyframeDictionary</a> dictionaries, a sequence of 1.1098 + <code>DOMString</code>s, a combination of both, or 1.1099 + a single <code>DOMString</code>. 1.1100 + </p> 1.1101 + <p> 1.1102 + <code>DOMString</code>s are used to create keyframes with an 1.1103 + offset of 1. 1.1104 + When the list of keyframes is a sequence consisting entirely of 1.1105 + <code>DOMString</code>s the offsets of the newly created 1.1106 + <a>Keyframe</a>s are distributed evenly from 0 to 1. 1.1107 + </p> 1.1108 + <p> 1.1109 + The <var>property</var>, <var>operation</var> and 1.1110 + <var>compositeOperation</var> arguments are assigned to the 1.1111 + attributes of the same names. 1.1112 + </p> 1.1113 + <p> 1.1114 + The <var>frames</var> argument is processed as follows: 1.1115 + </p> 1.1116 + <ol> 1.1117 + <li>Let <var>effect</var> be the 1.1118 + <a>KeyframeAnimationEffect</a> currently under construction. 1.1119 + </li> 1.1120 + <li> 1.1121 + <p> 1.1122 + The processing of <var>frames</var> depends on its type as 1.1123 + follows: 1.1124 + </p> 1.1125 + <dl class="switch"> 1.1126 + <dt>If <var>frames</var> is a <code>DOMString</code>,</dt> 1.1127 + <dd> 1.1128 + <ol> 1.1129 + <li> 1.1130 + Let <var>frame</var> be a new <a>Keyframe</a> 1.1131 + constructed from a <a>KeyframeDictionary</a> whose 1.1132 + <code>value</code> member is set to 1.1133 + <var>frames</var> and whose other members are set 1.1134 + to their default values. 1.1135 + </li> 1.1136 + <li> 1.1137 + Call 1.1138 + <code><var>effect</var>.frames.add(<var>frame</var>)</code>. 1.1139 + </li> 1.1140 + </ol> 1.1141 + </dd> 1.1142 + <dt>If <var>frames</var> is a sequence of <code>(DOMString 1.1143 + or <a>KeyframeDictionary</a>)</code>,</dt> 1.1144 + <dd> 1.1145 + <ol> 1.1146 + <li>Set a flag <var>all strings</var> to 1.1147 + <code>true</code>.</li> 1.1148 + <li> 1.1149 + For each <var>item</var> in <var>frames</var>: 1.1150 + <ol> 1.1151 + <li> 1.1152 + <dl class="switch"> 1.1153 + <dt>If <var>item</var> is 1.1154 + a <code>DOMString</code>,</dt> 1.1155 + <dd> 1.1156 + Let <var>frame</var> be a new <a>Keyframe</a> 1.1157 + constructed from a <a>KeyframeDictionary</a> 1.1158 + whose <code>value</code> member is set to 1.1159 + <var>item</var> and whose other members are 1.1160 + set to their default values. 1.1161 + </dd> 1.1162 + <dt>Otherwise (<var>item</var> is 1.1163 + a <a>KeyframeDictionary</a>),</dt> 1.1164 + <dd> 1.1165 + <ol> 1.1166 + <li> 1.1167 + Let <var>frame</var> be a new 1.1168 + <a>Keyframe</a> constructed by calling 1.1169 + <code>Keyframe(<var>item</var>)</code>. 1.1170 + </li> 1.1171 + <li> 1.1172 + Set <var>all strings</var> to 1.1173 + <code>false</code>. 1.1174 + </li> 1.1175 + </ol> 1.1176 + </dd> 1.1177 + </dl> 1.1178 + </li> 1.1179 + <li> 1.1180 + Call 1.1181 + <code><var>effect</var>.frames.add(<var>frame</var>)</code>. 1.1182 + </li> 1.1183 + </ol> 1.1184 + </li> 1.1185 + <li>If flag <var>all strings</var> is 1.1186 + <code>true</code> call 1.1187 + <code><var>effect</var>.frames.distribute()</code>. 1.1188 + </li> 1.1189 + </ol> 1.1190 + </dd> 1.1191 + </dl> 1.1192 + </li> 1.1193 + </ol> 1.1194 + </dd> 1.1195 + <dt>attribute DOMString property</dt> 1.1196 + <dd> 1.1197 + The name of the target property or attribute. 1.1198 + </dd> 1.1199 + <dt>readonly attribute KeyframeList frames</dt> 1.1200 + <dd> 1.1201 + The series of values that make up this effect sorted by their 1.1202 + offset within the iteration duration of the animation. 1.1203 + </dd> 1.1204 + </dl> 1.1205 + </section> 1.1206 + <section> 1.1207 + <h3>The <code>KeyframeList</code> interface</h3> 1.1208 + <p> 1.1209 + The <a>KeyframeList</a> object is a collection of <a>Keyframe</a> 1.1210 + objects sorted by the offset of each <a>Keyframe</a>. 1.1211 + </p> 1.1212 + <dl title="interface KeyframeList" class="idl"> 1.1213 + <dt>readonly attribute unsigned long length</dt> 1.1214 + <dd> 1.1215 + The number of frames in the list. 1.1216 + </dd> 1.1217 + <dt>void clear ()</dt> 1.1218 + <dd> 1.1219 + Removes all frames from this list. 1.1220 + </dd> 1.1221 + <dt>getter Keyframe? (unsigned long index)</dt> 1.1222 + <dd> 1.1223 + Returns the frame at <code>index</code> if it exists or 1.1224 + <code>null</code> otherwise. 1.1225 + </dd> 1.1226 + <dt>Keyframe add((Keyframe or KeyframeDictionary) frame)</dt> 1.1227 + <dd> 1.1228 + <p> 1.1229 + Adds <var>frame</var> to the list such that the list remains 1.1230 + sorted by the offset of the frames. 1.1231 + </p> 1.1232 + <p> 1.1233 + If <var>frame</var> is of type <a>KeyframeDictionary</a> then 1.1234 + a <a>Keyframe</a> object is first constructed by calling 1.1235 + <code>Keyframe(<var>frame</var>)</code> before adding the 1.1236 + newly constructed <a>Keyframe</a> to the list. 1.1237 + </p> 1.1238 + <p> 1.1239 + If there already exists a frame in this list with offset 1.1240 + <code><var>frame</var>.offset</code>, the newly added 1.1241 + <var>frame</var> will appear in the list <em>after</em> the 1.1242 + already existing frames in the list with the same offset. 1.1243 + </p> 1.1244 + <p> 1.1245 + If <var>frame</var> is already part of another <a>KeyframeList</a> 1.1246 + it is first removed from that list before being added to this 1.1247 + list. 1.1248 + </p> 1.1249 + <p> 1.1250 + Exceptions: 1.1251 + </p> 1.1252 + <dl class="exceptions"> 1.1253 + <dt>DOMException of type <code>IndexSizeError</code></dt> 1.1254 + <dd> 1.1255 + Raised if <var>frame</var> is a <a>KeyframeDictionary</a> whose 1.1256 + offset is outside the range [0,1] or missing. 1.1257 + </dd> 1.1258 + </dl> 1.1259 + </dd> 1.1260 + <dt>Keyframe? remove(unsigned long index)</dt> 1.1261 + <dd> 1.1262 + Removes the frame at position <var>index</var> and returns it. 1.1263 + If index is outside the range [0, length), then <code>null</code> is 1.1264 + returned. 1.1265 + </dd> 1.1266 + <dt>long indexOf(Keyframe frame)</dt> 1.1267 + <dd> 1.1268 + Returns the index of <var>frame</var> within the list. If 1.1269 + <var>frame</var> is not a member of the list, returns 1.1270 + <code>-1</code>. 1.1271 + </dd> 1.1272 + <dt>KeyframeList distribute()</dt> 1.1273 + <dd> 1.1274 + <p> 1.1275 + Adjusts the offsets of the frames in the list such that the 1.1276 + offsets are spaced equidistantly whilst maintaining their current 1.1277 + order and such that the first frame (when there are multiple 1.1278 + frames) has offset 0 and the last frame (if any) has offset 1. 1.1279 + </p> 1.1280 + <p> 1.1281 + For <var>frame</var> at position <var>i</var> in the list where 1.1282 + 0 ≤ <var>i</var> < <code>length</code>, an offset will be 1.1283 + assigned equal to <code>i / (length - 1)</code> unless 1.1284 + <code>length</code> is 1 in which case it will be given offset 1.1285 + 1. 1.1286 + </p> 1.1287 + <p> 1.1288 + After applying the changes, this list is returned. 1.1289 + </p> 1.1290 + </dd> 1.1291 + </dl> 1.1292 + <div class="annotation"> 1.1293 + <p> 1.1294 + The following changes for making keyframes easier to work with in 1.1295 + future have been proposed: 1.1296 + </p> 1.1297 + <pre class="example sh_javascript"> 1.1298 +// Currently you have to do this 1.1299 +effect.frames.add({ property: 'left', offset: 0.3, value: '100px' }); 1.1300 + 1.1301 +// It would be nice if you could also do this 1.1302 +effect.frames.add(0.3, 'left', '100px'); 1.1303 + 1.1304 +// Also, fetching by offset would be good 1.1305 + 1.1306 +// Returns the last frame with offset 0.3 if there is one. 1.1307 +// If there is none, does the interpolation and returns a new frame? 1.1308 +var frame = effect.frames['0.3']; 1.1309 + </pre> 1.1310 + </div> 1.1311 + </section> 1.1312 + <section> 1.1313 + <h3>The <code>Keyframe</code> interface</h3> 1.1314 + <p> 1.1315 + A <a>Keyframe</a> represents a moment within an animation that has 1.1316 + a specified value to be applied to the target property or attribute. 1.1317 + In between such moments values may be interpolated or filled based on 1.1318 + the <a>TimingFunction</a> specified on the <a>TimedItem</a> where the 1.1319 + <a>Keyframe</a> is used, or on the previous <a>Keyframe</a>. 1.1320 + </p> 1.1321 + <div class="issue"> 1.1322 + <p> 1.1323 + Currently a <a>Keyframe</a> can only target a single property which 1.1324 + is defined on the <a>KeyframeAnimationEffect</a>. 1.1325 + This is different to CSS. 1.1326 + Is this something we want to change? 1.1327 + It would complicate the API, of course, but is it worth it? 1.1328 + </p> 1.1329 + </div> 1.1330 + <p> 1.1331 + <dl title="interface Keyframe" class="idl"> 1.1332 + <dt>Constructor (KeyframeDictionary dictionary)</dt> 1.1333 + <dd> 1.1334 + <p> 1.1335 + Creates a new <a>Keyframe</a> object using the parameters 1.1336 + specified in <var>dictionary</var>. 1.1337 + </p> 1.1338 + <p> 1.1339 + <code><var>dictionary</var>.offset</code> is clamped to the 1.1340 + range [0, 1] before setting. 1.1341 + </p> 1.1342 + </dd> 1.1343 + <dt>attribute DOMString value</dt> 1.1344 + <dd> 1.1345 + The value to assign to the target attribute or property at the 1.1346 + given offset. 1.1347 + </dd> 1.1348 + <dt>attribute double offset</dt> 1.1349 + <dd> 1.1350 + <p> 1.1351 + A value between 0 and 1 inclusive representing the offset 1.1352 + within the iteration duration of the animation where this value 1.1353 + should appear. 1.1354 + </p> 1.1355 + <p> 1.1356 + If this keyframe belongs to a <a>KeyframeList</a>, changes to 1.1357 + this value cause the <a>KeyframeList</a> to be immediately 1.1358 + re-sorted using a stable sort such that all children are ordered 1.1359 + by their offset but children with identical offsets retain their 1.1360 + relative position in the list. 1.1361 + </p> 1.1362 + <p> 1.1363 + Exceptions: 1.1364 + </p> 1.1365 + <dl class="exceptions"> 1.1366 + <dt>DOMException of type <code>IndexSizeError</code></dt> 1.1367 + <dd> 1.1368 + Raised on setting a value outside the range [0,1]. 1.1369 + </dd> 1.1370 + </dl> 1.1371 + </dd> 1.1372 + <dt>attribute TimingFunction? timingFunction</dt> 1.1373 + <dd> 1.1374 + <p> 1.1375 + The timing function to apply between this keyframe and the 1.1376 + next keyframe in any <a>KeyframeList</a> in which this object 1.1377 + appears. 1.1378 + </p> 1.1379 + <p> 1.1380 + May be <code>null</code> in which case linear interpolation will 1.1381 + be used. 1.1382 + </p> 1.1383 + </dd> 1.1384 + </dl> 1.1385 + </p> 1.1386 + </section> 1.1387 + <section> 1.1388 + <h3>The <code>KeyframeDictionary</code> dictionary</h3> 1.1389 + <p> 1.1390 + To simplify creation of <a>Keyframe</a> objects 1.1391 + a <code>KeyframeDictionary</code> can be used. 1.1392 + </p> 1.1393 + <p> 1.1394 + The members of the dictionary correspond to attributes in the 1.1395 + <a>Keyframe</a> interface which provides a more complete description 1.1396 + of their meaning and usage. 1.1397 + </p> 1.1398 + <dl title="dictionary KeyframeDictionary" class="idl"> 1.1399 + <dt>DOMString value = ""</dt> 1.1400 + <dd> 1.1401 + The value to assign to the target attribute or property at the given 1.1402 + offset. 1.1403 + </dd> 1.1404 + <dt>double offset = 1</dt> 1.1405 + <dd> 1.1406 + A value between 0 and 1 (inclusive) representing the offset within 1.1407 + the iteration duration of the animation where this value should 1.1408 + appear. 1.1409 + </dd> 1.1410 + <dt>TimingFunction? timingFunction = null</dt> 1.1411 + <dd> 1.1412 + The timing function to apply between this keyframe and the 1.1413 + next keyframe in any <a>KeyframeList</a> in which this object 1.1414 + appears. 1.1415 + </dd> 1.1416 + </dl> 1.1417 + </section> 1.1418 + <section> 1.1419 + <h3>The <code>PathAnimationEffect</code> interface</h3> 1.1420 + <dl title="[Constructor] interface PathAnimationEffect 1.1421 + : AnimationEffect" class="idl"> 1.1422 + <dt>attribute SVGPathSegList segments</dt> 1.1423 + <dd> 1.1424 + The list of segments that make up this path. 1.1425 + </dd> 1.1426 + <dt>attribute boolean rotate</dt> 1.1427 + <dd> 1.1428 + True if objects animating along this path should be rotated 1.1429 + such that their positive x axis is aligned with the direction of 1.1430 + movement along the path. 1.1431 + </dd> 1.1432 + </dl> 1.1433 + </section> 1.1434 + <section> 1.1435 + <h3>The <code>GroupedAnimationEffect</code> interface</h3> 1.1436 + <p> 1.1437 + The <code>GroupedAnimationEffect</code> interface represents a 1.1438 + set of animation effects that share the same 1.1439 + <code>AnimationTemplate</code> parent. 1.1440 + </p> 1.1441 + <p class="todo"> 1.1442 + If the group contains multiple effects that target the same property 1.1443 + does order in the group matter? If so, we need to add a means for 1.1444 + re-ordering the group other than popping and pushing. For example, 1.1445 + <code>insertBefore</code>. 1.1446 + </p> 1.1447 + <dl title="interface GroupedAnimationEffect : AnimationEffect" 1.1448 + class="idl"> 1.1449 + <dt>Constructor (object properties)</dt> 1.1450 + <dd> 1.1451 + <p class="todo"> 1.1452 + TBD whilst we decide whether we need this interface or whether we 1.1453 + can merge it with <a>KeyframeAnimationEffect</a> somehow. 1.1454 + </p> 1.1455 + </dd> 1.1456 + <dt>readonly attribute unsigned long length</dt> 1.1457 + <dd> 1.1458 + The number of animation effects in the group. 1.1459 + </dd> 1.1460 + <dt>void clear()</dt> 1.1461 + <dd> 1.1462 + Removes all effects from this group. 1.1463 + </dd> 1.1464 + <dt>getter AnimationEffect? (unsigned long index)</dt> 1.1465 + <dd> 1.1466 + Returns the effect at <var>index</var> if it exists, or 1.1467 + <code>null</code> otherwise. 1.1468 + </dd> 1.1469 + <dt>AnimationEffect add(AnimationEffect effect)</dt> 1.1470 + <dd> 1.1471 + <p> 1.1472 + Appends <code>effect</code> to the end of the group such that 1.1473 + <code>group.indexOf(<var>effect</var>)</code> equals 1.1474 + <code>group.length - 1</code>. 1.1475 + </p> 1.1476 + <p class="todo"> 1.1477 + I'm assuming that <a>AnimationEffect</a>s can be shared amongst 1.1478 + animations and groups. 1.1479 + Or does <var>effect</var> need to be removed from any previous 1.1480 + <a>AnimationEffect</a>s or <a>Animation</a>s first? 1.1481 + </p> 1.1482 + </dd> 1.1483 + <dt>AnimationEffect? remove(unsigned long index)</dt> 1.1484 + <dd> 1.1485 + Removes the effect at <code>index</code> and returns it. If 1.1486 + <var>index</var> is outside the range [0, <code>length</code>), then 1.1487 + <code>null</code> is returned. 1.1488 + </dd> 1.1489 + <dt>long indexOf(AnimationEffect effect)</dt> 1.1490 + <dd> 1.1491 + Returns the index of <var>effect</var> within the group. 1.1492 + If <var>effect</var> is not a member of the group, returns 1.1493 + <code>-1</code>. 1.1494 + </dd> 1.1495 + </dl> 1.1496 + </section> 1.1497 + <section> 1.1498 <h3>Extensions to the <code>Document</code> interface</h3> 1.1499 <p> 1.1500 The following extensions are made to the <a 1.1501 @@ -5592,6 +5654,12 @@ 1.1502 start reporting events to content expecting only CSS animations). 1.1503 </p> 1.1504 </div> 1.1505 + <div class="todo"> 1.1506 + Clarify somewhere that timing events are a property of the <em>timing 1.1507 + model</em> hence they continue to fire even if there is no animation 1.1508 + effect and even if the target property is in a <code>display: 1.1509 + none</code> block. 1.1510 + </div> 1.1511 <section> 1.1512 <h3>The <code>TimingEvent</code> interface</h3> 1.1513 <dl title="interface TimingEvent : Event" class="idl">