mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Support triggering multiple animations per animation property
We also now use the computed (rather than cascaded) values when triggering animations.
This commit is contained in:
parent
18477b0d84
commit
84762021b8
Notes:
github-actions[bot]
2025-10-27 09:49:34 +00:00
Author: https://github.com/Calme1709
Commit: 84762021b8
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6585
Reviewed-by: https://github.com/AtkinsSJ ✅
11 changed files with 322 additions and 231 deletions
|
|
@ -37,6 +37,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/StringStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
|
||||
#include <LibWeb/CSS/StyleValues/TextUnderlinePositionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
|
||||
#include <LibWeb/Layout/BlockContainer.h>
|
||||
#include <LibWeb/Layout/Node.h>
|
||||
|
|
@ -53,7 +54,6 @@ ComputedProperties::~ComputedProperties() = default;
|
|||
void ComputedProperties::visit_edges(Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_animation_name_source);
|
||||
visitor.visit(m_transition_property_source);
|
||||
}
|
||||
|
||||
|
|
@ -1934,6 +1934,108 @@ Optional<FlyString> ComputedProperties::view_transition_name() const
|
|||
return {};
|
||||
}
|
||||
|
||||
Vector<ComputedProperties::AnimationProperties> ComputedProperties::animations() const
|
||||
{
|
||||
// CSS Animations are defined by binding keyframes to an element using the animation-* properties. These list-valued
|
||||
// properties, which are all longhands of the animation shorthand, form a coordinating list property group with
|
||||
// animation-name as the coordinating list base property and each item in the coordinated value list defining the
|
||||
// properties of a single animation effect.
|
||||
auto const& coordinated_properties = assemble_coordinated_value_list(
|
||||
PropertyID::AnimationName,
|
||||
{ PropertyID::AnimationDuration,
|
||||
PropertyID::AnimationTimingFunction,
|
||||
PropertyID::AnimationIterationCount,
|
||||
PropertyID::AnimationDirection,
|
||||
PropertyID::AnimationPlayState,
|
||||
PropertyID::AnimationDelay,
|
||||
PropertyID::AnimationFillMode,
|
||||
PropertyID::AnimationComposition,
|
||||
PropertyID::AnimationName });
|
||||
|
||||
Vector<AnimationProperties> animations;
|
||||
|
||||
for (size_t i = 0; i < coordinated_properties.get(PropertyID::AnimationName)->size(); i++) {
|
||||
// https://drafts.csswg.org/css-animations-1/#propdef-animation-name
|
||||
// none: No keyframes are specified at all, so there will be no animation. Any other animations properties
|
||||
// specified for this animation have no effect.
|
||||
if (coordinated_properties.get(PropertyID::AnimationName).value()[i]->to_keyword() == Keyword::None)
|
||||
continue;
|
||||
|
||||
auto animation_name_style_value = coordinated_properties.get(PropertyID::AnimationName).value()[i];
|
||||
auto animation_duration_style_value = coordinated_properties.get(PropertyID::AnimationDuration).value()[i];
|
||||
auto animation_timing_function_style_value = coordinated_properties.get(PropertyID::AnimationTimingFunction).value()[i];
|
||||
auto animation_iteration_count_style_value = coordinated_properties.get(PropertyID::AnimationIterationCount).value()[i];
|
||||
auto animation_direction_style_value = coordinated_properties.get(PropertyID::AnimationDirection).value()[i];
|
||||
auto animation_play_state_style_value = coordinated_properties.get(PropertyID::AnimationPlayState).value()[i];
|
||||
auto animation_delay_style_value = coordinated_properties.get(PropertyID::AnimationDelay).value()[i];
|
||||
auto animation_fill_mode_style_value = coordinated_properties.get(PropertyID::AnimationFillMode).value()[i];
|
||||
auto animation_composition_style_value = coordinated_properties.get(PropertyID::AnimationComposition).value()[i];
|
||||
|
||||
auto duration = [&] {
|
||||
if (animation_duration_style_value->is_time())
|
||||
return animation_duration_style_value->as_time().time().to_milliseconds();
|
||||
|
||||
if (animation_duration_style_value->is_calculated())
|
||||
return animation_duration_style_value->as_calculated().resolve_time({}).value().to_milliseconds();
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}();
|
||||
|
||||
auto timing_function = EasingFunction::from_style_value(animation_timing_function_style_value);
|
||||
|
||||
auto iteration_count = [&] {
|
||||
if (animation_iteration_count_style_value->to_keyword() == Keyword::Infinite)
|
||||
return AK::Infinity<double>;
|
||||
|
||||
if (animation_iteration_count_style_value->is_number())
|
||||
return animation_iteration_count_style_value->as_number().number();
|
||||
|
||||
if (animation_iteration_count_style_value->is_calculated())
|
||||
return animation_iteration_count_style_value->as_calculated().resolve_number({}).value();
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}();
|
||||
|
||||
auto direction = keyword_to_animation_direction(animation_direction_style_value->to_keyword()).value();
|
||||
auto play_state = keyword_to_animation_play_state(animation_play_state_style_value->to_keyword()).value();
|
||||
auto delay = [&] {
|
||||
if (animation_delay_style_value->is_time())
|
||||
return animation_delay_style_value->as_time().time().to_milliseconds();
|
||||
|
||||
if (animation_delay_style_value->is_calculated())
|
||||
return animation_delay_style_value->as_calculated().resolve_time({}).value().to_milliseconds();
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}();
|
||||
auto fill_mode = keyword_to_animation_fill_mode(animation_fill_mode_style_value->to_keyword()).value();
|
||||
auto composition = keyword_to_animation_composition(animation_composition_style_value->to_keyword()).value();
|
||||
|
||||
auto name = [&] {
|
||||
if (animation_name_style_value->is_custom_ident())
|
||||
return animation_name_style_value->as_custom_ident().custom_ident();
|
||||
|
||||
if (animation_name_style_value->is_string())
|
||||
return animation_name_style_value->as_string().string_value();
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}();
|
||||
|
||||
animations.append(AnimationProperties {
|
||||
.duration = duration,
|
||||
.timing_function = timing_function,
|
||||
.iteration_count = iteration_count,
|
||||
.direction = direction,
|
||||
.play_state = play_state,
|
||||
.delay = delay,
|
||||
.fill_mode = fill_mode,
|
||||
.composition = composition,
|
||||
.name = name,
|
||||
});
|
||||
}
|
||||
|
||||
return animations;
|
||||
}
|
||||
|
||||
MaskType ComputedProperties::mask_type() const
|
||||
{
|
||||
auto const& value = property(PropertyID::MaskType);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue