-
Notifications
You must be signed in to change notification settings - Fork 757
Description
From @birtles on September 14, 2016 7:47
Just a thought about how we could simplify the API and make it more consistent.
Currently, we manage timing properties using the following interfaces:
AnimationEffectTimingProperties— property bag for passing to constructors etc.ComputedTimingProperties— extendsAnimationEffectTimingPropertieswith some extra properties we computeAnimationEffectTimingReadOnly— Live object with getters for reading the specified timing properties. Fortunately, this happens to have the same members asAnimationEffectTimingPropertiesso you can pass it to constructors/methods that expect aAnimationEffectTimingPropertiesand it should work.AnimationEffectTiming— Subclass ofAnimationEffectTimingReadOnlythat adds getters for the different parameters (used by mutable effects, i.e. those not tied to CSS)
In practice it looks like this:
// Set up a new animation
const anim = elem.animate({...}, { duration: 2000, fill: 'auto' });
// Read back the specified values
anim.effect.timing.duration; // 2000
anim.effect.timing.fill; // 'auto'
// Read back computed values
anim.effect.getComputedTiming().duration; // 2000
anim.effect.getComputedTiming().fill; // 'none'
// NOTE: |fill| and |duration| are a little bit special in that they allow 'auto'
// values that get computed into something else. It's not particularly useful, though,
// until we have groups (where, e.g., a group's auto duration computes to the length
// of its children).
// Read other computed values
anim.effect.getComputedTiming().activeDuration // 2000
anim.effect.getComputedTiming().progress // 0.0
// Update specified values
anim.effect.timing.duration *= 2;
anim.effect.timing.iterations++;The parallel here is with style:
anim.effect.timing=~elem.style(sort of, kind of)anim.effect.getComputedTiming=~window.getComputedStyle(elem)
However, for keyframes we do something completely different. We don't have live keyframe objects since that would be hard and instead we just use getKeyframes() and setKeyframes().
In addition, keyframe offsets can be computed. The author can omit them and we'll fill them in. We don't just fill in the offset member with the computed value when we return keyframes using getKeyframes(), however, since if we did that you couldn't take the result of getKeyframes() and pass it to setKeyframes() on another effect without freezing the offsets at that point (and losing the ability to auto-distribute keyframes from then on). Instead, we return the computed offset as a separate member: computedOffset.
So my thought here was:
- Drop
AnimationEffectTimingReadOnly. - Drop
AnimationEffectTiming. - Drop
effect.timing. - Rename
effect.getComputedTiming()toeffect.getTiming(). - Extend
ComputedTimingPropertiesto includecomputedDurationandcomputedFill. - Add
effect.setTiming()that takes anAnimationEffectTimingProperties(whichComputedTimingPropertiesextends so you could pass the result ofgetTiming()tosetTiming()).
Advantages:
- 2 fewer interfaces
- Fewer live objects
- Consistency within the API — keyframes and timing properties follow the same idiom
- Bulk setting of timing properties is easier
Disadvantages:
- More awkward to update an individual timing property, e.g.
// Current API
anim.effect.timing.duration *= 2;
// Proposed API
const updatedTiming = anim.effect.getTiming();
updatedTiming.duration *= 2;
anim.effect.setTiming(updatedTiming);- More inefficient to update individual timing properties since you need to read and write these property bags. From what I understand, at least for Gecko, that can be quite slow.
I do wonder how common those last two items are, though. (And for the first one, if you're just blindingly overwriting the value, you can use Object.assign() or, one day, the object spread operator to write it more compactly.)
The other consideration is this proposal may be less forwards compatible. For example, suppose we extend iterations to take a keyword value. Presumably it will still compute to a float. Code that currently calls anim.effect.getComputedTiming().iterations would continue to work when this new property is used. However, under this proposal, code that calls anim.effect.getTiming().iterations would need to be updated to call anim.effect.getTiming.computedIterations instead.
That said, I think we already have this problem in that anyone currently calling anim.effect.timing.iterations and assuming it will be a float (which I expect is not uncommon since it's less to type than anim.effect.getComputedTiming().iterations) will have the same problem.
@shans, @dstockwell Any thoughts about this?
@heycam, @bzbarsky Is returning snapshot objects generally the preferred approach over maintaining live objects?
Copied from original issue: w3c/web-animations#168