Title: [181655] trunk
Revision
181655
Author
[email protected]
Date
2015-03-17 12:01:46 -0700 (Tue, 17 Mar 2015)

Log Message

Implement Scroll Container Animation Triggers
https://bugs.webkit.org/show_bug.cgi?id=142732

Reviewed by Simon Fraser.

Source/WebCore:

Test: animations/trigger-container-scroll-simple.html

Basic implementation of container-scroll. It only checks
the page scroll position for trigger values (not the scrolling
container in an overflow).

* css/CSSComputedStyleDeclaration.cpp: Add CSSPropertyWebkitAnimationTrigger
so that this property will appear in the inspector.

* page/FrameView.cpp:
(WebCore::FrameView::sendScrollEvent): If the page has scrolled, let the animation
controller know about it.

* page/animation/AnimationBase.cpp:
(WebCore::AnimationBase::updateStateMachine): Whitespace fix.
(WebCore::AnimationBase::fireAnimationEventsIfNeeded): If there is a trigger,
and the scroll position is past it, then tell the state machine that
we should start.
(WebCore::AnimationBase::timeToNextService): Use the scroll position as
an input to the update timer if a trigger is involved.

* page/animation/AnimationController.cpp:
(WebCore::AnimationControllerPrivate::ensureCompositeAnimation): Add whitespace.
(WebCore::AnimationControllerPrivate::scrollWasUpdated): Call updateAnimations.
(WebCore::AnimationController::scrollWasUpdated): Call into AnimationControllerPrivate.
* page/animation/AnimationController.h:
* page/animation/AnimationControllerPrivate.h:

* page/animation/CompositeAnimation.cpp: Keep a record of whether we have a scroll
triggered animation.
(WebCore::CompositeAnimation::CompositeAnimation):
(WebCore::CompositeAnimation::updateKeyframeAnimations):
* page/animation/CompositeAnimation.h:
(WebCore::CompositeAnimation::hasScrollTriggeredAnimation):
* platform/animation/Animation.cpp:
(WebCore::Animation::operator=):

LayoutTests:

Test that checks if an animation only triggers when the page
is scrolled.

* animations/trigger-container-scroll-simple-expected.txt: Added.
* animations/trigger-container-scroll-simple.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (181654 => 181655)


--- trunk/LayoutTests/ChangeLog	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/LayoutTests/ChangeLog	2015-03-17 19:01:46 UTC (rev 181655)
@@ -1,3 +1,16 @@
+2015-03-17  Dean Jackson  <[email protected]>
+
+        Implement Scroll Container Animation Triggers
+        https://bugs.webkit.org/show_bug.cgi?id=142732
+
+        Reviewed by Simon Fraser.
+
+        Test that checks if an animation only triggers when the page
+        is scrolled.
+
+        * animations/trigger-container-scroll-simple-expected.txt: Added.
+        * animations/trigger-container-scroll-simple.html: Added.
+
 2015-03-17  Brent Fulgham  <[email protected]>
 
         [Win] Skip some IndexDB tests that don't apply on Windows.

Added: trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt (0 => 181655)


--- trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt	2015-03-17 19:01:46 UTC (rev 181655)
@@ -0,0 +1,6 @@
+This element should begin animating only when the page scrolls to 20px from the top. The animation is almost instantaneous, so it will snap to its final position. Remember to scroll to the top of the page before reloading!
+
+Value before animation is applied: auto (should be auto)
+Value with animation but no scroll: 0px (should be 0px)
+Value with animation after scroll: 100px (should be 100px)
+
Property changes on: trunk/LayoutTests/animations/trigger-container-scroll-simple-expected.txt
___________________________________________________________________

Added: svn:mime-type

Added: svn:keywords

Added: svn:eol-style

Added: trunk/LayoutTests/animations/trigger-container-scroll-simple.html (0 => 181655)


--- trunk/LayoutTests/animations/trigger-container-scroll-simple.html	                        (rev 0)
+++ trunk/LayoutTests/animations/trigger-container-scroll-simple.html	2015-03-17 19:01:46 UTC (rev 181655)
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<style>
+body {
+    height: 2000px;
+}
+
+#box {
+    position: relative;
+    width: 20px;
+    height: 20px;
+    background-color: blue;
+}
+
+.animating {
+    animation-name: slide;
+    animation-duration: 1ms;
+    animation-fill-mode: forwards;
+    -webkit-animation-trigger: container-scroll(20px);
+}
+
+@-webkit-keyframes slide {
+  from {
+      left: 0px;
+  }
+  to {
+      left: 100px;
+  }
+}
+</style>
+<script>
+
+var results;
+var box;
+
+if (window.testRunner) {
+    window.testRunner.dumpAsText();
+    window.testRunner.waitUntilDone();
+}
+
+function runTest() {
+    results = document.getElementById("results");
+    box = document.getElementById("box");
+    results.innerHTML = "Value before animation is applied: " + window.getComputedStyle(box).left + " (should be auto)<br>";
+    box.className = "animating";
+    setTimeout(checkValueWithoutScroll, 0);
+}
+
+function checkValueWithoutScroll() {
+    results.innerHTML += "Value with animation but no scroll: " + window.getComputedStyle(box).left + " (should be 0px)<br>";
+    window.scrollTo(0, 30);
+    setTimeout(checkValueWithScroll, 0);
+}
+
+function checkValueWithScroll() {
+    results.innerHTML += "Value with animation after scroll: " + window.getComputedStyle(box).left + " (should be 100px)<br>";
+    if (window.testRunner)
+        window.testRunner.notifyDone();
+}
+
+window.addEventListener("load", runTest, false);
+
+</script>
+
+<p>This element should begin animating only when the page scrolls to 20px from
+the top. The animation is almost instantaneous, so it will snap to its final
+position. Remember to scroll to the top of the page before reloading!</p>
+<div id="box"></div>
+
+<div id="results"></div>
Property changes on: trunk/LayoutTests/animations/trigger-container-scroll-simple.html
___________________________________________________________________

Added: svn:mime-type

Added: svn:keywords

Added: svn:eol-style

Modified: trunk/Source/WebCore/ChangeLog (181654 => 181655)


--- trunk/Source/WebCore/ChangeLog	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/ChangeLog	2015-03-17 19:01:46 UTC (rev 181655)
@@ -1,3 +1,47 @@
+2015-03-17  Dean Jackson  <[email protected]>
+
+        Implement Scroll Container Animation Triggers
+        https://bugs.webkit.org/show_bug.cgi?id=142732
+
+        Reviewed by Simon Fraser.
+
+        Test: animations/trigger-container-scroll-simple.html
+
+        Basic implementation of container-scroll. It only checks
+        the page scroll position for trigger values (not the scrolling
+        container in an overflow).
+
+        * css/CSSComputedStyleDeclaration.cpp: Add CSSPropertyWebkitAnimationTrigger
+        so that this property will appear in the inspector.
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::sendScrollEvent): If the page has scrolled, let the animation
+        controller know about it.
+
+        * page/animation/AnimationBase.cpp:
+        (WebCore::AnimationBase::updateStateMachine): Whitespace fix.
+        (WebCore::AnimationBase::fireAnimationEventsIfNeeded): If there is a trigger,
+        and the scroll position is past it, then tell the state machine that
+        we should start.
+        (WebCore::AnimationBase::timeToNextService): Use the scroll position as
+        an input to the update timer if a trigger is involved.
+
+        * page/animation/AnimationController.cpp:
+        (WebCore::AnimationControllerPrivate::ensureCompositeAnimation): Add whitespace.
+        (WebCore::AnimationControllerPrivate::scrollWasUpdated): Call updateAnimations.
+        (WebCore::AnimationController::scrollWasUpdated): Call into AnimationControllerPrivate.
+        * page/animation/AnimationController.h:
+        * page/animation/AnimationControllerPrivate.h:
+
+        * page/animation/CompositeAnimation.cpp: Keep a record of whether we have a scroll
+        triggered animation.
+        (WebCore::CompositeAnimation::CompositeAnimation):
+        (WebCore::CompositeAnimation::updateKeyframeAnimations):
+        * page/animation/CompositeAnimation.h:
+        (WebCore::CompositeAnimation::hasScrollTriggeredAnimation):
+        * platform/animation/Animation.cpp:
+        (WebCore::Animation::operator=):
+
 2015-03-17  Simon Fraser  <[email protected]>
 
         Move some code from LogicalSelectionOffsetCaches into RenderElement

Modified: trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp (181654 => 181655)


--- trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp	2015-03-17 19:01:46 UTC (rev 181655)
@@ -245,6 +245,7 @@
     CSSPropertyWebkitAnimationName,
     CSSPropertyWebkitAnimationPlayState,
     CSSPropertyWebkitAnimationTimingFunction,
+    CSSPropertyWebkitAnimationTrigger,
     CSSPropertyWebkitAppearance,
     CSSPropertyWebkitBackfaceVisibility,
     CSSPropertyWebkitBackgroundClip,

Modified: trunk/Source/WebCore/page/FrameView.cpp (181654 => 181655)


--- trunk/Source/WebCore/page/FrameView.cpp	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/FrameView.cpp	2015-03-17 19:01:46 UTC (rev 181655)
@@ -4374,6 +4374,9 @@
 {
     frame().eventHandler().sendScrollEvent();
     frame().eventHandler().dispatchFakeMouseMoveEventSoon();
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    frame().animation().scrollWasUpdated();
+#endif
 }
 
 void FrameView::removeChild(Widget& widget)

Modified: trunk/Source/WebCore/page/animation/AnimationBase.cpp (181654 => 181655)


--- trunk/Source/WebCore/page/animation/AnimationBase.cpp	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationBase.cpp	2015-03-17 19:01:46 UTC (rev 181655)
@@ -40,6 +40,7 @@
 #include "Logging.h"
 #include "RenderBox.h"
 #include "RenderStyle.h"
+#include "RenderView.h"
 #include "UnitBezier.h"
 #include <algorithm>
 #include <wtf/CurrentTime.h>
@@ -198,6 +199,7 @@
     switch (m_animationState) {
         case AnimationState::New:
             ASSERT(input == AnimationStateInput::StartAnimation || input == AnimationStateInput::PlayStateRunning || input == AnimationStateInput::PlayStatePaused);
+
             if (input == AnimationStateInput::StartAnimation || input == AnimationStateInput::PlayStateRunning) {
                 m_requestedStartTime = beginAnimationUpdateTime();
                 LOG(Animations, "%p AnimationState %s -> StartWaitTimer", this, nameForState(m_animationState));
@@ -457,12 +459,29 @@
     
     // Check for start timeout
     if (m_animationState == AnimationState::StartWaitTimer) {
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        if (m_animation->trigger() && m_animation->trigger()->isScrollAnimationTrigger()) {
+            if (m_object) {
+                LayoutSize offset = m_object->view().frameView().scrollOffsetForFixedPosition();
+                ScrollAnimationTrigger* scrollTrigger = static_cast<ScrollAnimationTrigger*>(m_animation->trigger().get());
+                if (offset.height().toFloat() > scrollTrigger->startValue().value())
+                    updateStateMachine(AnimationStateInput::StartTimerFired, 0);
+            }
+
+            return;
+        }
+#endif
         if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay())
             updateStateMachine(AnimationStateInput::StartTimerFired, 0);
         return;
     }
     
     double elapsedDuration = beginAnimationUpdateTime() - m_startTime;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    if (m_animation->trigger() && m_animation->trigger()->isScrollAnimationTrigger())
+        elapsedDuration = getElapsedTime();
+#endif
+
     // FIXME: we need to ensure that elapsedDuration is never < 0. If it is, this suggests that
     // we had a recalcStyle() outside of beginAnimationUpdate()/endAnimationUpdate().
     // Also check in getTimeToNextEvent().
@@ -521,6 +540,17 @@
         return -1;
     
     if (m_animationState == AnimationState::StartWaitTimer) {
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        if (m_animation->trigger()->isScrollAnimationTrigger()) {
+            if (m_object) {
+                float currentScrollOffset = m_object->view().frameView().scrollOffsetForFixedPosition().height().toFloat();
+                ScrollAnimationTrigger* scrollTrigger = static_cast<ScrollAnimationTrigger*>(m_animation->trigger().get());
+                if (currentScrollOffset >= scrollTrigger->startValue().value() && (!scrollTrigger->hasEndValue() || currentScrollOffset <= scrollTrigger->endValue().value()))
+                    return 0;
+            }
+            return -1;
+        }
+#endif
         double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime);
         return std::max(timeFromNow, 0.0);
     }
@@ -672,7 +702,7 @@
 
 double AnimationBase::getElapsedTime() const
 {
-    if (paused())    
+    if (paused())
         return m_pauseTime - m_startTime;
     if (m_startTime <= 0)
         return 0;

Modified: trunk/Source/WebCore/page/animation/AnimationController.cpp (181654 => 181655)


--- trunk/Source/WebCore/page/animation/AnimationController.cpp	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationController.cpp	2015-03-17 19:01:46 UTC (rev 181655)
@@ -92,6 +92,7 @@
         result.iterator->value = CompositeAnimation::create(this);
         renderer.setIsCSSAnimating(true);
     }
+
     return *result.iterator->value;
 }
 
@@ -514,6 +515,13 @@
     removeFromAnimationsWaitingForStartTimeResponse(animation);
 }
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+void AnimationControllerPrivate::scrollWasUpdated()
+{
+    updateAnimations(CallSetChanged);
+}
+#endif
+
 AnimationController::AnimationController(Frame& frame)
     : m_data(std::make_unique<AnimationControllerPrivate>(frame))
 {
@@ -700,4 +708,11 @@
     return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property);
 }
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+void AnimationController::scrollWasUpdated()
+{
+    m_data->scrollWasUpdated();
+}
+#endif
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/animation/AnimationController.h (181654 => 181655)


--- trunk/Source/WebCore/page/animation/AnimationController.h	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationController.h	2015-03-17 19:01:46 UTC (rev 181655)
@@ -86,6 +86,10 @@
     
     static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID);
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    void scrollWasUpdated();
+#endif
+
 private:
     const std::unique_ptr<AnimationControllerPrivate> m_data;
 };

Modified: trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h (181654 => 181655)


--- trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/AnimationControllerPrivate.h	2015-03-17 19:01:46 UTC (rev 181655)
@@ -117,6 +117,10 @@
     bool allowsNewAnimationsWhileSuspended() const { return m_allowsNewAnimationsWhileSuspended; }
     void setAllowsNewAnimationsWhileSuspended(bool);
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    void scrollWasUpdated();
+#endif
+
 private:
     void animationTimerFired();
 

Modified: trunk/Source/WebCore/page/animation/CompositeAnimation.cpp (181654 => 181655)


--- trunk/Source/WebCore/page/animation/CompositeAnimation.cpp	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/CompositeAnimation.cpp	2015-03-17 19:01:46 UTC (rev 181655)
@@ -43,6 +43,9 @@
 
 CompositeAnimation::CompositeAnimation(AnimationControllerPrivate* animationController)
     : m_animationController(animationController)
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    , m_hasScrollTriggeredAnimation(false)
+#endif
 {
     m_suspended = animationController->isSuspended() && !animationController->allowsNewAnimationsWhileSuspended();
 }
@@ -222,7 +225,11 @@
         // Mark all existing animations as no longer active.
         for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
             it->value->setIndex(-1);
-            
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+        m_hasScrollTriggeredAnimation = false;
+#endif
+
         // Toss the animation order map.
         m_keyframeAnimationOrderMap.clear();
 
@@ -245,7 +252,12 @@
                     // If this animation is postActive, skip it so it gets removed at the end of this function.
                     if (keyframeAnim->postActive())
                         continue;
-                    
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+                    if (animation.trigger()->isScrollAnimationTrigger())
+                        m_hasScrollTriggeredAnimation = true;
+#endif
+
                     // This one is still active.
 
                     // Animations match, but play states may differ. Update if needed.
@@ -265,6 +277,12 @@
                     for (auto it = keyframeAnim->keyframes().beginProperties(), end = keyframeAnim->keyframes().endProperties(); it != end; ++it)
                         LOG(Animations, "  property %s", getPropertyName(*it));
 #endif
+
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+                    if (animation.trigger()->isScrollAnimationTrigger())
+                        m_hasScrollTriggeredAnimation = true;
+#endif
+
                     m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
                 }
                 

Modified: trunk/Source/WebCore/page/animation/CompositeAnimation.h (181654 => 181655)


--- trunk/Source/WebCore/page/animation/CompositeAnimation.h	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/page/animation/CompositeAnimation.h	2015-03-17 19:01:46 UTC (rev 181655)
@@ -80,6 +80,10 @@
     bool pauseTransitionAtTime(CSSPropertyID, double);
     unsigned numberOfActiveAnimations() const;
 
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    bool hasScrollTriggeredAnimation() const { return m_hasScrollTriggeredAnimation; }
+#endif
+
 private:
     CompositeAnimation(AnimationControllerPrivate*);
 
@@ -87,13 +91,16 @@
     void updateKeyframeAnimations(RenderElement*, RenderStyle* currentStyle, RenderStyle* targetStyle);
     
     typedef HashMap<int, RefPtr<ImplicitAnimation>> CSSPropertyTransitionsMap;
-    typedef HashMap<AtomicStringImpl*, RefPtr<KeyframeAnimation>>  AnimationNameMap;
+    typedef HashMap<AtomicStringImpl*, RefPtr<KeyframeAnimation>> AnimationNameMap;
 
     AnimationControllerPrivate* m_animationController;
     CSSPropertyTransitionsMap m_transitions;
     AnimationNameMap m_keyframeAnimations;
     Vector<AtomicStringImpl*> m_keyframeAnimationOrderMap;
     bool m_suspended;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    bool m_hasScrollTriggeredAnimation;
+#endif
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/animation/Animation.cpp (181654 => 181655)


--- trunk/Source/WebCore/platform/animation/Animation.cpp	2015-03-17 18:58:59 UTC (rev 181654)
+++ trunk/Source/WebCore/platform/animation/Animation.cpp	2015-03-17 19:01:46 UTC (rev 181655)
@@ -94,6 +94,9 @@
     m_delay = o.m_delay;
     m_duration = o.m_duration;
     m_timingFunction = o.m_timingFunction;
+#if ENABLE(CSS_ANIMATIONS_LEVEL_2)
+    m_trigger = o.m_trigger;
+#endif
     m_direction = o.m_direction;
     m_fillMode = o.m_fillMode;
     m_playState = o.m_playState;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to