Skip to content

Commit 090b1fe

Browse files
committed
1. No longer mark Finished transition as CascadeLevel::Transitions
2. Implement step 4.1, 4.2 of CSS transition 3. Remove unnecessary `mut` for readability Signed-off-by: Euclid Ye <[email protected]>
1 parent 7ee9643 commit 090b1fe

File tree

2 files changed

+78
-8
lines changed

2 files changed

+78
-8
lines changed

style/animation.rs

+75-5
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl PropertyAnimation {
7070
let to = AnimationValue::from_computed_values(property_declaration, new_style)?;
7171
let duration = duration.seconds() as f64;
7272

73-
if from == to || duration == 0.0 {
73+
if from == to || duration <= 0.0 {
7474
return None;
7575
}
7676

@@ -1015,11 +1015,60 @@ impl ElementAnimationSet {
10151015
if transition.state == AnimationState::Finished {
10161016
continue;
10171017
}
1018-
if transitioning_properties.contains(transition.property_animation.property_id()) {
1018+
// Step 3 in https://drafts.csswg.org/css-transitions/#starting
1019+
// "If the element has a running transition or completed transition for the property,
1020+
// and there is not a matching transition-property value, then implementations
1021+
// must cancel the running transition or remove the completed transition from the set of completed transitions."
1022+
let transition_property_id = transition.property_animation.property_id();
1023+
if !transitioning_properties.contains(transition_property_id) {
1024+
transition.state = AnimationState::Canceled;
1025+
self.dirty = true;
10191026
continue;
10201027
}
1021-
transition.state = AnimationState::Canceled;
1022-
self.dirty = true;
1028+
1029+
1030+
// Never panic: We made sure in fn start_transition_if_applicable if a transition is valid, after_change_to is also valid
1031+
let after_change_to = AnimationValue::from_computed_values(transition_property_id, &after_change_style).unwrap();
1032+
// Step 4
1033+
// "If the element has a running transition for the property, there is a matching transition-property value,
1034+
// and the end value of the running transition is not equal to the value of the property in the after-change style, then:"
1035+
if transition.property_animation.to != after_change_to {
1036+
// index for after-change transition declaration
1037+
let index = after_change_style.transition_properties().position(|declared_transition| declared_transition.property
1038+
.as_borrowed()
1039+
.to_physical(after_change_style.writing_mode) == transition_property_id).unwrap();
1040+
1041+
let now = context.current_time_for_animations;
1042+
let after_change_style = after_change_style.get_ui();
1043+
let allow_discrete = after_change_style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1044+
let current_val = transition.calculate_value(now);
1045+
let not_transitionable =
1046+
(!transition_property_id.is_animatable() || (!allow_discrete && transition_property_id.is_discrete_animatable()))
1047+
|| (!allow_discrete && !current_val.interpolable_with(&after_change_to));
1048+
1049+
let combined_duration = after_change_style.transition_duration_mod(index).seconds() + after_change_style.transition_delay_mod(index).seconds();
1050+
// Step 4.1
1051+
//"If the current value of the property in the running transition is equal
1052+
// to the value of the property in the after-change style,
1053+
// or if these two values are not transitionable, then implementations must cancel the running transition."
1054+
1055+
if current_val == after_change_to || not_transitionable {
1056+
transition.state = AnimationState::Canceled;
1057+
self.dirty = true;
1058+
continue;
1059+
}
1060+
// Step 4.2
1061+
// "Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the
1062+
// running transition is not transitionable with the value of the property in the after-change style,
1063+
// then implementations must cancel the running transition."
1064+
else if combined_duration <= 0.0 {
1065+
transition.state = AnimationState::Canceled;
1066+
self.dirty = true;
1067+
continue;
1068+
}
1069+
1070+
//Step 4.4
1071+
}
10231072
}
10241073
}
10251074

@@ -1079,6 +1128,7 @@ impl ElementAnimationSet {
10791128
return;
10801129
}
10811130

1131+
// Step 1 in https://drafts.csswg.org/css-transitions/#starting
10821132
// We are going to start a new transition, but we might have to update
10831133
// it if we are replacing a reversed transition.
10841134
let reversing_adjusted_start_value = property_animation.from.clone();
@@ -1129,6 +1179,26 @@ impl ElementAnimationSet {
11291179
Some(map)
11301180
}
11311181

1182+
/// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
1183+
/// transitions that are not canceled or finished at the given time value.
1184+
pub fn get_value_map_for_running_transitions(&self, now: f64) -> Option<AnimationValueMap> {
1185+
if !self.has_active_transition() {
1186+
return None;
1187+
}
1188+
1189+
let mut map =
1190+
AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1191+
for transition in &self.transitions {
1192+
if transition.state == AnimationState::Canceled || transition.state == AnimationState::Finished {
1193+
continue;
1194+
}
1195+
let value = transition.calculate_value(now);
1196+
map.insert(value.id().to_owned(), value);
1197+
}
1198+
1199+
Some(map)
1200+
}
1201+
11321202
/// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
11331203
/// active animations at the given time value.
11341204
pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
@@ -1235,7 +1305,7 @@ impl DocumentAnimationSet {
12351305
self.sets
12361306
.read()
12371307
.get(key)
1238-
.and_then(|set| set.get_value_map_for_active_transitions(time))
1308+
.and_then(|set| set.get_value_map_for_running_transitions(time))
12391309
.map(|map| {
12401310
let block = PropertyDeclarationBlock::from_animation_value_map(&map);
12411311
Arc::new(shared_lock.wrap(block))

style/matching.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ trait PrivateMatchMethods: TElement {
605605
fn process_animations_for_pseudo(
606606
&self,
607607
context: &mut StyleContext<Self>,
608-
old_styles: &mut ElementStyles,
608+
old_styles: &ElementStyles,
609609
new_resolved_styles: &mut ResolvedElementStyles,
610610
pseudo_element: PseudoElement,
611611
) {
@@ -687,8 +687,8 @@ trait PrivateMatchMethods: TElement {
687687
fn process_animations_for_style(
688688
&self,
689689
context: &mut StyleContext<Self>,
690-
old_values: &mut Option<Arc<ComputedValues>>,
691-
new_values: &mut Arc<ComputedValues>,
690+
old_values: &Option<Arc<ComputedValues>>,
691+
new_values: &Arc<ComputedValues>,
692692
pseudo_element: Option<PseudoElement>,
693693
) -> bool {
694694
use crate::animation::{AnimationSetKey, AnimationState};

0 commit comments

Comments
 (0)