@@ -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) )
0 commit comments