@@ -70,7 +70,7 @@ impl PropertyAnimation {
70
70
let to = AnimationValue :: from_computed_values ( property_declaration, new_style) ?;
71
71
let duration = duration. seconds ( ) as f64 ;
72
72
73
- if from == to || duration = = 0.0 {
73
+ if from == to || duration < = 0.0 {
74
74
return None ;
75
75
}
76
76
@@ -1015,11 +1015,55 @@ impl ElementAnimationSet {
1015
1015
if transition. state == AnimationState :: Finished {
1016
1016
continue ;
1017
1017
}
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
+ if !transitioning_properties. contains ( transition. property_animation . property_id ( ) ) {
1023
+ transition. state = AnimationState :: Canceled ;
1024
+ self . dirty = true ;
1019
1025
continue ;
1020
1026
}
1021
- transition. state = AnimationState :: Canceled ;
1022
- self . dirty = true ;
1027
+
1028
+ let transition_property_id = transition. property_animation . property_id ( ) ;
1029
+ // Never panic: We made sure in fn start_transition_if_applicable if a transition is valid, after_change_to is also valid
1030
+ let after_change_to = AnimationValue :: from_computed_values ( transition_property_id, & after_change_style) . unwrap ( ) ;
1031
+ // Step 4
1032
+ // "If the element has a running transition for the property, there is a matching transition-property value,
1033
+ // and the end value of the running transition is not equal to the value of the property in the after-change style, then:"
1034
+ if transition. property_animation . to != after_change_to {
1035
+ // index for after-change transition declaration
1036
+ let index = after_change_style. transition_properties ( ) . position ( |declared_transition| declared_transition. property
1037
+ . as_borrowed ( )
1038
+ . to_physical ( after_change_style. writing_mode ) == transition_property_id) . unwrap ( ) ;
1039
+
1040
+ let now = context. current_time_for_animations ;
1041
+ let after_change_style = after_change_style. get_ui ( ) ;
1042
+ let allow_discrete: bool = after_change_style. transition_behavior_mod ( index) == TransitionBehavior :: AllowDiscrete ;
1043
+ let not_transitionable = !transition_property_id. is_animatable ( ) || ( !allow_discrete && transition_property_id. is_discrete_animatable ( ) ) ;
1044
+ let combined_duration = after_change_style. transition_duration_mod ( index) . seconds ( ) + after_change_style. transition_delay_mod ( index) . seconds ( ) ;
1045
+ // Step 4.1
1046
+ //"If the current value of the property in the running transition is equal
1047
+ // to the value of the property in the after-change style,
1048
+ // or if these two values are not transitionable, then implementations must cancel the running transition."
1049
+ let current_val = transition. calculate_value ( now) ;
1050
+ if current_val == after_change_to || not_transitionable {
1051
+ transition. state = AnimationState :: Canceled ;
1052
+ self . dirty = true ;
1053
+ continue ;
1054
+ }
1055
+ // Step 4.2
1056
+ // Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the
1057
+ // running transition is not transitionable with the value of the property in the after-change style,
1058
+ // then implementations must cancel the running transition.
1059
+ else if combined_duration <= 0.0 || current_val. interpolable_with ( & after_change_to) {
1060
+ transition. state = AnimationState :: Canceled ;
1061
+ self . dirty = true ;
1062
+ continue ;
1063
+ }
1064
+
1065
+ //Step 4.4
1066
+ }
1023
1067
}
1024
1068
}
1025
1069
@@ -1079,6 +1123,7 @@ impl ElementAnimationSet {
1079
1123
return ;
1080
1124
}
1081
1125
1126
+ // Step 1 in https://drafts.csswg.org/css-transitions/#starting
1082
1127
// We are going to start a new transition, but we might have to update
1083
1128
// it if we are replacing a reversed transition.
1084
1129
let reversing_adjusted_start_value = property_animation. from . clone ( ) ;
@@ -1129,6 +1174,26 @@ impl ElementAnimationSet {
1129
1174
Some ( map)
1130
1175
}
1131
1176
1177
+ /// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
1178
+ /// transitions that are not canceled or finished at the given time value.
1179
+ pub fn get_value_map_for_running_transitions ( & self , now : f64 ) -> Option < AnimationValueMap > {
1180
+ if !self . has_active_transition ( ) {
1181
+ return None ;
1182
+ }
1183
+
1184
+ let mut map =
1185
+ AnimationValueMap :: with_capacity_and_hasher ( self . transitions . len ( ) , Default :: default ( ) ) ;
1186
+ for transition in & self . transitions {
1187
+ if transition. state == AnimationState :: Canceled || transition. state == AnimationState :: Finished {
1188
+ continue ;
1189
+ }
1190
+ let value = transition. calculate_value ( now) ;
1191
+ map. insert ( value. id ( ) . to_owned ( ) , value) ;
1192
+ }
1193
+
1194
+ Some ( map)
1195
+ }
1196
+
1132
1197
/// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
1133
1198
/// active animations at the given time value.
1134
1199
pub fn get_value_map_for_active_animations ( & self , now : f64 ) -> Option < AnimationValueMap > {
@@ -1235,7 +1300,7 @@ impl DocumentAnimationSet {
1235
1300
self . sets
1236
1301
. read ( )
1237
1302
. get ( key)
1238
- . and_then ( |set| set. get_value_map_for_active_transitions ( time) )
1303
+ . and_then ( |set| set. get_value_map_for_running_transitions ( time) )
1239
1304
. map ( |map| {
1240
1305
let block = PropertyDeclarationBlock :: from_animation_value_map ( & map) ;
1241
1306
Arc :: new ( shared_lock. wrap ( block) )
0 commit comments