style: layout: Get actual keyframes working!

There are a few shortcomings, for example:

 * We don't do the same as other browsers when some properties are not specified
   in some of the keyframes, though this is easy to work out (though a bit more
   expensive in the sense that we should apply all the previous keyframes' style
   instead of just the previous and the next.

 * To trigger the initial animation, a restyle is necessary. Should be easy to
   do an initial restyle off-hand or something like that, but for now this is
   worked-around adding a :hover rule to the node.

   Also, the animation is resetted when the node is hovered. That's a bug, but
   is probably not so difficult to test.

 * A few things, mainly animation-direction, are not supported yet, but
   shouldn't be that hard to support.

Still a lot of work to do, but I think this approach might be ok.
This commit is contained in:
Emilio Cobos Álvarez 2016-06-21 00:02:25 +02:00
parent bc970596d6
commit cb3da24f08
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 68 additions and 16 deletions

View file

@ -26,7 +26,44 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
pipeline_id: PipelineId) {
let mut new_running_animations = vec![];
while let Ok(animation) = new_animations_receiver.try_recv() {
new_running_animations.push(animation)
let should_push = match animation {
Animation::Transition(..) => true,
Animation::Keyframes(ref node, ref name, ref state) => {
// If the animation was already present in the list for the
// node, just update its state, else push the new animation to
// run.
if let Some(ref mut animations) = running_animations.get_mut(node) {
// TODO: This being linear is probably not optimal.
match animations.iter_mut().find(|anim| match **anim {
Animation::Keyframes(_, ref anim_name, _) => *name == *anim_name,
Animation::Transition(..) => false,
}) {
Some(mut anim) => {
debug!("update_animation_state: Found other animation {}", name);
match *anim {
Animation::Keyframes(_, _, ref mut anim_state) => {
// NB: The important part is not touching
// the started_at field.
anim_state.duration = state.duration;
anim_state.iteration_state = state.iteration_state.clone();
anim_state.paused = state.paused;
anim_state.delay = state.delay;
false
}
_ => unreachable!(),
}
}
None => true,
}
} else {
true
}
}
};
if should_push {
new_running_animations.push(animation);
}
}
if running_animations.is_empty() && new_running_animations.is_empty() {
@ -54,8 +91,9 @@ pub fn update_animation_state(constellation_chan: &IpcSender<ConstellationMsg>,
*current += 1;
*current < *max
}
// Just tick it again.
KeyframesIterationState::Infinite => {
state.started_at += state.duration;
state.started_at += state.duration + state.delay;
true
}
}