瀏覽代碼

LibWeb: Implement Animation::play_state

Matthew Olsson 1 年之前
父節點
當前提交
fe40bdfc01

+ 41 - 2
Userland/Libraries/LibWeb/Animations/Animation.cpp

@@ -257,8 +257,39 @@ WebIDL::ExceptionOr<void> Animation::set_playback_rate(double new_playback_rate)
 // https://www.w3.org/TR/web-animations-1/#animation-play-state
 Bindings::AnimationPlayState Animation::play_state() const
 {
-    // FIXME: Implement
-    return Bindings::AnimationPlayState::Idle;
+    // The play state of animation, animation, at a given moment is the state corresponding to the first matching
+    // condition from the following:
+
+    // -> All of the following conditions are true:
+    //    - The current time of animation is unresolved, and
+    //    - the start time of animation is unresolved, and
+    //    - animation does not have either a pending play task or a pending pause task,
+    auto current_time = this->current_time();
+    if (!current_time.has_value() && !m_start_time.has_value() && !pending()) {
+        // → idle
+        return Bindings::AnimationPlayState::Idle;
+    }
+
+    // -> Either of the following conditions are true:
+    //    - animation has a pending pause task, or
+    //    - both the start time of animation is unresolved and it does not have a pending play task,
+    if (m_pending_pause_task == TaskState::Pending || (!m_start_time.has_value() && m_pending_play_task == TaskState::None)) {
+        // → paused
+        return Bindings::AnimationPlayState::Paused;
+    }
+
+    // -> For animation, current time is resolved and either of the following conditions are true:
+    //    - animation’s effective playback rate > 0 and current time ≥ associated effect end; or
+    //    - animation’s effective playback rate < 0 and current time ≤ 0,
+    auto effective_playback_rate = this->effective_playback_rate();
+    if (current_time.has_value() && ((effective_playback_rate > 0.0 && current_time.value() >= associated_effect_end()) || (effective_playback_rate < 0.0 && current_time.value() <= 0.0))) {
+        // → finished
+        return Bindings::AnimationPlayState::Finished;
+    }
+
+    // -> Otherwise,
+    //    → running
+    return Bindings::AnimationPlayState::Running;
 }
 
 // https://www.w3.org/TR/web-animations-1/#associated-effect-end
@@ -269,6 +300,14 @@ double Animation::associated_effect_end() const
     return m_effect ? m_effect->end_time() : 0.0;
 }
 
+// https://www.w3.org/TR/web-animations-1/#effective-playback-rate
+double Animation::effective_playback_rate() const
+{
+    // The effective playback rate of an animation is its pending playback rate, if set, otherwise it is the animation’s
+    // playback rate.
+    return m_pending_playback_rate.has_value() ? m_pending_playback_rate.value() : m_playback_rate;
+}
+
 // https://www.w3.org/TR/web-animations-1/#apply-any-pending-playback-rate
 void Animation::apply_any_pending_playback_rate()
 {

+ 4 - 0
Userland/Libraries/LibWeb/Animations/Animation.h

@@ -42,6 +42,9 @@ public:
 
     Bindings::AnimationReplaceState replace_state() const { return m_replace_state; }
 
+    // https://www.w3.org/TR/web-animations-1/#dom-animation-pending
+    bool pending() const { return m_pending_pause_task != TaskState::None || m_pending_play_task != TaskState::None; }
+
     // https://www.w3.org/TR/web-animations-1/#dom-animation-ready
     JS::NonnullGCPtr<JS::Object> ready() const { return *current_ready_promise()->promise(); }
 
@@ -62,6 +65,7 @@ private:
     };
 
     double associated_effect_end() const;
+    double effective_playback_rate() const;
 
     void apply_any_pending_playback_rate();
     WebIDL::ExceptionOr<void> silently_set_current_time(Optional<double>);

+ 1 - 2
Userland/Libraries/LibWeb/Animations/Animation.idl

@@ -15,8 +15,7 @@ interface Animation : EventTarget {
              attribute double                   playbackRate;
     readonly attribute AnimationPlayState       playState;
     readonly attribute AnimationReplaceState    replaceState;
-    // FIXME:
-    // readonly attribute boolean                  pending;
+    readonly attribute boolean                  pending;
     readonly attribute Promise<Animation>       ready;
     readonly attribute Promise<Animation>       finished;