- From: Brian Birtles <bbirtles@mozilla.com>
- Date: Wed, 08 Aug 2012 14:38:46 +0900
- To: "public-fx@w3.org" <public-fx@w3.org>
Web Animations minutes, 7 / 8 Aug 2012
Etherpad: https://etherpad.mozilla.org/ep/pad/view/ro.eiMsLaB5x-p/latest
Present: Dmitry Baranovskiy, Alex Danilo, Shane Stephens, Brian Birtles
Agenda:
1. Renaming Anim/AnimInstance
2. What time do you pass to seek()?
3. Liveness
4. Template classes
5. Removing the Timing interface
0. STATUS UPDATE
Dmitry checked in Enum support to respec.js. Works great.
Brian working on start(), stop(), reverse(), changeSpeed(), pausing etc.
One month out from SVGOpen.
Current work items:
1. Specification (Brian / Dmitry to provide support)
Shane to address TODOs in "Primitive animation operations" section
2!. Presentation (Alex)
(3). SVG Integration spec
4. Emulator (Shane and hopefully Dmitry)
Shane to send Dmitry current state, so he can get familiar with the
code.
(5). CSS Integration spec
1. RENAMING Anim/AnimInstance
Now that we have the global Animate function, script does not need to
refer to the Anim interface directly as often.
Can we rename as follows?
s/Anim/AnimProto/
s/AnimInstance/Anim/
AnimTemplate may be better than AnimProto to avoid confusion with
Anim.__proto__ and AnimPrototype
> We will rename Anim -> AnimTemplate, AnimInstance -> Anim
2. WHAT TIME DO YOU PASS TO SEEK()?
Suppose I have this animation:
anim {
delay: 3s;
from: 100px;
to: 200px;
dur: 5s;
}
(Forget the syntax, this is some CSS-SVG neutral ground syntax I just
made up)
3s after the document loads it begins animating from 100px to 200px. It
finishes 8s after the document loads.
Later I call anim.seek(3).
What is the result?
a) 100px
b) 160px
c) something else?
Answers:
Alex and Brian: (b)
Shane: (a) or global time
Dmitry: (a) or (b)
Currently the answer as spec'ced is (a). If (b) is more intuitive then I
need to revise how seek() works. The up-shot is we can probably get rid
of the whole concept of item time which is probably confusing to most
people.
What if you repeat the experiment, assuming that the animation was not
triggered until after 30s (i.e. has a start time of 30s)?
> Discussion about whether delay should be considered an intrinsic or
extrinsic part of an item's timeline. General consensus that the model
is currently angled towards it being intrinsic (e.g. the sandwich model
sorts by start time and delay allows items to be shifted in their
"effect" but still sorted by the sandwich model). Some disagreement wrt.
"Active" being only when an item is filling or animating - i.e. an item
can be in delay but not "Active" if there's no fill.
> Resolved that it's intrinsic. i.e. seek(3) includes delay
> Brian to look at rephrasing section talking about "Active" animations
3. LIVENESS
Some proposals to consider:
PROPOSAL A: Explicit delinking
(from François REMY)
Similar to existing but don't automatically break liveness. Rather, if a
change is made to a linked instance (live instance) throw an exception
and require an explicit call to makeIndependent (delink?) in order to
make the change.
Shane: I like this for its brittleness - if you do something unexpected
we make sure you know about it up-front.
PROPOSAL B: Everything is individually overridable except the
AnimationFunction which requires explicit delinking
Originally when we tried to approach liveness we did what you'd expect,
i.e.
var template = new AnimTemplate;
template.timing.speed = 3;
var anim = template.animate(...);
? template.timing.speed // 3
? anim.timing.speed // 3
anim.timing.speed = 4;
? template.timing.speed // 3
? anim.timing.speed // 4
template.timing.speed = 5;
? template.timing.speed // 5
? anim.timing.speed // 4
But we ran into two problems:
i) How to reset each of these properties?
ii) Following this scheme through to all the different types of
AnimFunction (including those to be added in the future, and
script-defined ones) and supporting this property-by-property tracking
on each of their sub-properties seemed like a real pain.
With regard to (i), I've defined TimedItem.animationDuration so that you
can override the computed value. You can reset it by just assiging it to
undefined or null (currently I've gone for undefined, but we can change
it to null). I spoke to Cameron McCormack (WedIDL spec editor) and he
says that's fine.
For (ii) we could say we do property-by-property overriding for the
timing properties (i.e. everything on TimedItem and Timing), but treat
the func property specially, i.e. if you try to change the copy attached
to the instance it will throw an exception and you need to call clone
(or something similar) before you can change it.
Unlike A, this lets you make small tweaks to the timing without losing
liveness of the rest.
Shane: This works OK but do we have a strong use-case for tweaking the
timing without losing liveness? If not, then maybe this is too complex.
PROPOSAL C: No liveness
Just drop liveness altogether. SVG and CSS do the bookkeeping of copying
property changes across.
(Brian: This does raise some questions though. Will SVG and CSS just
blindly overwrite the values on the instances? If not, you basically run
into the same problems outlined at the start of proposal B.)
Shane: I don't like this mainly because liveness will be useful to
advanced script users too, so we'd be replacing 1 painful mechanism with
3 painful mechanisms that mostly do the same thing.
Note that if we go with C, we could introduce A (or even B) in a later
version.
Alex and Dmitry: favour doing C for now, introducing A later
Dmitry: This is probably dependent on what we decide to do with the
Timing interface.
Shane: Objections:
- practically, this is already needed for SVG/CSS integration and
authors will also sometimes want this feature (liveness), so we should
support it
- philosophically, if we're having such a hard time getting it right,
why just shift the burden to SVG/CSS?
> We'll come back to this in light of what we decide regard to Template
classes at the Timing interface
4. TEMPLATE CLASSES
This is related to liveness but orthogonal to most proposals. The
question is, do we need template classes?
One alternative we could have is to have Anim objects that have no
target / startTime / parent, very lonely individuals, but nevertheless
welcome. In a sense, these are the templates.
To create an "instance" you clone an Anim object and give it a target /
startTime / parent along the way.
Anim objects might have 'defaultTarget' and 'defaultParent' properties
to simplify cloning. i.e. anim.animate(4).
Liveness could still be achieved by having clones refer back to their
source.
What this gives us is:
* A lot less interfaces to specify. It's simpler because you don't have
to match up these parallel hierarchies.
* We could possibly also get rid of the Timing interface since the main
reason it has been split out is to share the definitions between
template and instance
Some downsides are:
* Confusing to have some Anim objects that work as templates and some
that are actual animations
* In future it's probably useful to overload just the templates. e.g.
for the SVG integration, define a special SVGAnimTemplate that does all
the complicated work of managing syncbase timing etc. and then just
spawns these very simple vanilla Anim objects at the appropriate times.
Shane: This has some intriguing possibilities. I would modify it
slightly to exclude *just* the target, and allow the "template" versions
to be inserted into timelines like "normal" ones. These would then act
essentially as spacers. This removes the first downside, and means that
every Anim object is both a template and potentially an animation.
In fact, untargetted Anim objects can even be parented by the global
group, as this is a "par" group.
The second downside doesn't really seem like a downside to me :)
Basically the mechanism is roughly the same, and we're only having a bit
of trouble thinking about it because we started down the other path already.
Brian: Concerned about having all these dummy animations in the tree
that are simply there to be cloned. It's confusing when you walk the
tree and half of the "animations" are not actually doing any animation.
> Need to flesh out the details to see if this is workable:
Kicking ground for the idea: https://etherpad.mozilla.org/07VpfyGtdw
5. REMOVING THE Timing INTERFACE
I (Brian) find the Timing interface a little confusing. For example, you
have:
anim.timing.startDelay
BUT
anim.startTime
There's good reason for it--the delay is a property of the template, the
start time is related to the specific instantiation--but I think authors
will find it confusing. What do you think?
There are two reasons for the existence of the Timing interface:
* Share definitions between AnimTemplate and Anim
* To allow separation of specified and computed values
i.e. we have
anim.timing.iterationDuration -- the specified duration, can be null
meaning 'intrinsic duration' (e.g. for groups, videos etc.)
but we also have
anim.iterationDuration -- the calculated duration
I (Brian) was thinking about collapsing Timing into TimedItem/TimedTemplate.
This would give you:
interface TimedItem {
// Previous Timing interface
attribute float startDelay;
attribute unrestricted float? iterationDuration;
attribute unrestricted float iterationCount;
attribute float iterationStart;
attribute float speed;
attribute PlaybackDirection direction;
attribute TimingFunction timingFunction;
attribute FillMode fill;
// Existing TimedItem interface
readonly attribute float? animationTime;
attribute unrestricted float animationDuration;
readonly attribute float? iterationTime;
readonly attribute unrestricted float iterationDuration;
readonly attribute unsigned long? currentIteration;
attribute float startTime;
readonly attribute unrestricted float endTime;
readonly attribute AnimGroupInstance parentGroup;
readonly attribute float timeDrift;
void start (optional float timeFromNow = 0);
void stop (optional float timeFromNow = 0);
void pause ();
void unpause ();
bool getPauseState ();
bool isPaused ();
void seek (unsigned long itemTime);
void changeSpeed (float speed);
void reverse ();
void cancel ();
};
and:
interface TimedTemplate {
// Previous Timing interface
attribute float startDelay;
attribute unrestricted float? iterationDuration;
attribute unrestricted float iterationCount;
attribute float iterationStart;
attribute float speed;
attribute PlaybackDirection direction;
attribute TimingFunction timingFunction;
attribute FillMode fill;
// Existiing TimedTemplate interface
TimedItem animate (Element target, optional float startTime);
...
};
For the two versions of iterationDuration you could either have:
specifiedIterationDuration
computedIterationDuration
(or something a bit shorter)
Or just do like I've done with animationDuration. i.e. you can override
it, otherwise it reflects the intrinsic iteration duration. That doesn't
work so well, however, if we want the specified duration to take on
values like "20%" etc.
Regarding the definitions, you'd define it once (probably in
TimedTemplate since it appears first) and then just refer to those
definitions from TimedItem.
Which do you prefer?
Shane: I must admit I actually like the separation of specification and
computed values, which is what we have at the moment. If we roll these
in together, maybe prefixing the computed versions with "computed" could
be good? I don't think we'd also need a "specified" prefix.
Dmitry: Proposal to keep timing properties as properties, but convert
all dynamic properties into methods.
TimedItem.animationTime → TimedItem.animationTime() [or
TimedItem.getAnimationTime()]
This way it’s more clear that the value is not static and could be
potentially expensive to get. If we decide to make them writable we
could always allow the method to accept value or add setAnimationTime()
(which is obviously uglier). This will remove confusion:
anim.timing.startDelay
anim.startTime
or
anim.startDelay
anim.startTime()
Next meeting: 9 Aug 18:00 PDT / 10 Aug 11:00 AEST / 10 Aug 10:00 JST @
https://etherpad.mozilla.org/CVoYIc2pWz
Received on Wednesday, 8 August 2012 05:39:18 UTC