ladybird/Libraries/LibWeb/CSS/CSSAnimation.h
Andreas Kling 42bf301acd LibWeb: Apply animation-timing-function per keyframe interval
Per the CSS Animations spec, the animation-timing-function property
describes how the animation progresses between each pair of keyframes,
not as an overall effect-level timing function.

Previously we set it as the effect-level timing function on the
AnimationEffect, which caused easing to be applied to the global
animation progress. This made animations with multiple keyframes
"pause" at the start and end of the full animation cycle instead of
easing smoothly between each pair of keyframes.

Now we:
- Store per-keyframe easing in ResolvedKeyFrame from @keyframes rules
- Store the default easing on CSSAnimation instead of on the effect
- Apply per-keyframe easing to the interval progress during
  interpolation, falling back to the CSS animation's default easing
- Also store per-keyframe easing from JS-created KeyframeEffects to
  avoid incorrectly applying CSS default easing to replaced effects
2026-03-21 23:16:32 -05:00

53 lines
1.8 KiB
C++

/*
* Copyright (c) 2024, Matthew Olsson <mattco@serenityos.org>.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Animations/Animation.h>
#include <LibWeb/CSS/ComputedProperties.h>
#include <LibWeb/CSS/EasingFunction.h>
#include <LibWeb/CSS/StyleValues/StyleValue.h>
namespace Web::CSS {
// https://www.w3.org/TR/css-animations-2/#cssanimation
class CSSAnimation : public Animations::Animation {
WEB_PLATFORM_OBJECT(CSSAnimation, Animations::Animation);
GC_DECLARE_ALLOCATOR(CSSAnimation);
public:
static GC::Ref<CSSAnimation> create(JS::Realm&);
FlyString const& animation_name() const { return m_animation_name; }
void set_animation_name(FlyString const& animation_name) { m_animation_name = animation_name; }
virtual Animations::AnimationClass animation_class() const override;
virtual int class_specific_composite_order(GC::Ref<Animations::Animation> other) const override;
void apply_css_properties(ComputedProperties::AnimationProperties const&);
EasingFunction const& default_easing() const { return m_default_easing; }
virtual void set_timeline_for_bindings(GC::Ptr<Animations::AnimationTimeline> timeline) override;
private:
explicit CSSAnimation(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual bool is_css_animation() const override { return true; }
// https://drafts.csswg.org/css-animations-2/#dom-cssanimation-animationname
FlyString m_animation_name;
// https://drafts.csswg.org/css-animations-1/#animation-timing-function
// The default per-keyframe easing, from the animation-timing-function property on the element.
EasingFunction m_default_easing { EasingFunction::ease() };
HashTable<CSS::PropertyID> m_ignored_css_properties;
};
}