@@ -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,60 @@ 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
+ 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 ;
1019
1026
continue ;
1020
1027
}
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
+ }
1023
1072
}
1024
1073
}
1025
1074
@@ -1079,6 +1128,7 @@ impl ElementAnimationSet {
1079
1128
return ;
1080
1129
}
1081
1130
1131
+ // Step 1 in https://drafts.csswg.org/css-transitions/#starting
1082
1132
// We are going to start a new transition, but we might have to update
1083
1133
// it if we are replacing a reversed transition.
1084
1134
let reversing_adjusted_start_value = property_animation. from . clone ( ) ;
@@ -1129,6 +1179,26 @@ impl ElementAnimationSet {
1129
1179
Some ( map)
1130
1180
}
1131
1181
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
+
1132
1202
/// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
1133
1203
/// active animations at the given time value.
1134
1204
pub fn get_value_map_for_active_animations ( & self , now : f64 ) -> Option < AnimationValueMap > {
@@ -1235,7 +1305,7 @@ impl DocumentAnimationSet {
1235
1305
self . sets
1236
1306
. read ( )
1237
1307
. 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) )
1239
1309
. map ( |map| {
1240
1310
let block = PropertyDeclarationBlock :: from_animation_value_map ( & map) ;
1241
1311
Arc :: new ( shared_lock. wrap ( block) )
0 commit comments