mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
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:
parent
bc970596d6
commit
cb3da24f08
2 changed files with 68 additions and 16 deletions
|
@ -41,10 +41,12 @@ pub enum KeyframesIterationState {
|
|||
/// This structure represents the current keyframe animation state, i.e., the
|
||||
/// duration, the current and maximum iteration count, and the state (either
|
||||
/// playing or paused).
|
||||
// TODO: unify the use of f32/f64 in this file.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyframesAnimationState {
|
||||
pub started_at: f64,
|
||||
pub duration: f64,
|
||||
pub delay: f64,
|
||||
pub iteration_state: KeyframesIterationState,
|
||||
pub paused: bool,
|
||||
}
|
||||
|
@ -294,6 +296,7 @@ pub fn maybe_start_animations<Impl: SelectorImplExt>(context: &SharedStyleContex
|
|||
.send(Animation::Keyframes(node, name.clone(), KeyframesAnimationState {
|
||||
started_at: animation_start,
|
||||
duration: duration as f64,
|
||||
delay: delay as f64,
|
||||
iteration_state: iteration_state,
|
||||
paused: paused,
|
||||
})).unwrap();
|
||||
|
@ -383,36 +386,46 @@ where Impl: SelectorImplExt,
|
|||
let mut total_progress = (now - started_at) / total_duration;
|
||||
if total_progress < 0. {
|
||||
warn!("Negative progress found for animation {:?}", name);
|
||||
return;
|
||||
}
|
||||
if total_progress > 1. {
|
||||
total_progress = 1.;
|
||||
}
|
||||
|
||||
debug!("update_style_for_animation: anim \"{}\", steps: {:?}, state: {:?}, progress: {}", name, animation.steps, state, total_progress);
|
||||
|
||||
let mut last_keyframe = None;
|
||||
let mut target_keyframe = None;
|
||||
let mut last_keyframe_position = None;
|
||||
let mut target_keyframe_position = None;
|
||||
|
||||
// TODO: we could maybe binary-search this?
|
||||
for i in 1..animation.steps.len() {
|
||||
// TODO: we could maybe binary-search this? Also, find is probably a
|
||||
// bit more idiomatic here?
|
||||
for i in 0..animation.steps.len() {
|
||||
if total_progress as f32 <= animation.steps[i].start_percentage.0 {
|
||||
// We might have found our current keyframe.
|
||||
last_keyframe = target_keyframe;
|
||||
target_keyframe = Some(&animation.steps[i]);
|
||||
target_keyframe_position = Some(i);
|
||||
if i != 0 {
|
||||
last_keyframe_position = Some(i - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let target_keyframe = match target_keyframe {
|
||||
Some(current) => current,
|
||||
debug!("update_style_for_animation: keyframe from {:?} to {:?}", last_keyframe_position, target_keyframe_position);
|
||||
|
||||
let target_keyframe = match target_keyframe_position {
|
||||
Some(target) => &animation.steps[target],
|
||||
None => {
|
||||
warn!("update_style_for_animation: No current keyframe found for animation {:?} at progress {}", name, total_progress);
|
||||
// TODO: The 0. case falls here, maybe we should just resort
|
||||
// to the first keyframe instead.
|
||||
warn!("update_style_for_animation: No current keyframe found for animation \"{}\" at progress {}", name, total_progress);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let last_keyframe = match last_keyframe {
|
||||
Some(last_keyframe) => last_keyframe,
|
||||
let last_keyframe = match last_keyframe_position {
|
||||
Some(last) => &animation.steps[last],
|
||||
None => {
|
||||
warn!("update_style_for_animation: No last keyframe found for animation {:?} at progress {}", name, total_progress);
|
||||
warn!("update_style_for_animation: No last keyframe found for animation \"{}\" at progress {}", name, total_progress);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -441,20 +454,21 @@ where Impl: SelectorImplExt,
|
|||
let mut style_changed = false;
|
||||
|
||||
for transition_property in &animation.properties_changed {
|
||||
debug!("update_style_for_animation: scanning prop {:?} for animation {}", transition_property, name);
|
||||
debug!("update_style_for_animation: scanning prop {:?} for animation \"{}\"", transition_property, name);
|
||||
if let Some(property_animation) = PropertyAnimation::from_transition_property(*transition_property,
|
||||
timing_function,
|
||||
Time(relative_duration as f32),
|
||||
&from_style,
|
||||
&target_style) {
|
||||
debug!("update_style_for_animation: got property animation for prop {:?}", transition_property);
|
||||
debug!("update_style_for_animation: {:?}", property_animation);
|
||||
property_animation.update(Arc::make_mut(&mut new_style), relative_progress);
|
||||
style_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if style_changed {
|
||||
debug!("update_style_for_animation: got style change in animation {:?}", name);
|
||||
debug!("update_style_for_animation: got style change in animation \"{}\"", name);
|
||||
if let Some(damage) = damage {
|
||||
*damage = *damage | Damage::compute(Some(style), &new_style);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue