зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1676791 - Part 3: Implement the computation of timing. r=hiro
This patch focus on the timing computation of animation effects. We have to compute the correct progress based on the scroll offsets. Now we simplify the implementation only from 0% to 100%. The test cases will be added in the last patch once we hook the scroll timeline to the CSS animation. Differential Revision: https://phabricator.services.mozilla.com/D129101
This commit is contained in:
Родитель
8604a51732
Коммит
193a6c3d7a
|
@ -441,6 +441,10 @@ class Animation : public DOMEventTargetHelper,
|
|||
PostUpdate();
|
||||
}
|
||||
|
||||
bool UsingScrollTimeline() const {
|
||||
return mTimeline && mTimeline->IsScrollTimeline();
|
||||
}
|
||||
|
||||
protected:
|
||||
void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
|
||||
void CancelNoUpdate();
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#define mozilla_dom_AnimationEffect_h
|
||||
|
||||
#include "mozilla/ComputedTiming.h"
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/ScrollTimeline.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/TimingParams.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
@ -19,7 +21,6 @@ class ErrorResult;
|
|||
|
||||
namespace dom {
|
||||
|
||||
class Animation;
|
||||
class KeyframeEffect;
|
||||
struct ComputedEffectTiming;
|
||||
struct EffectTiming;
|
||||
|
@ -49,7 +50,15 @@ class AnimationEffect : public nsISupports, public nsWrapperCache {
|
|||
virtual void UpdateTiming(const OptionalEffectTiming& aTiming,
|
||||
ErrorResult& aRv);
|
||||
|
||||
const TimingParams& SpecifiedTiming() const { return mTiming; }
|
||||
const TimingParams& SpecifiedTiming() const {
|
||||
return mAnimation && mAnimation->UsingScrollTimeline()
|
||||
// This returns the TimingParams which is used for getting
|
||||
// ComputedTiming. For now, we assume all the callers of
|
||||
// SpecifiedTiming() want to use this for scroll-timelines
|
||||
// (and let the animation events be an undefined part).
|
||||
? ScrollTimeline::GetTiming()
|
||||
: mTiming;
|
||||
}
|
||||
void SetSpecifiedTiming(TimingParams&& aTiming);
|
||||
|
||||
// This function takes as input the timing parameters of an animation and
|
||||
|
|
|
@ -101,6 +101,8 @@ class AnimationTimeline : public nsISupports, public nsWrapperCache {
|
|||
|
||||
virtual Document* GetDocument() const = 0;
|
||||
|
||||
virtual bool IsScrollTimeline() const { return false; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIGlobalObject> mWindow;
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
|
@ -54,6 +57,39 @@ ScrollTimeline::ScrollTimeline(Document* aDocument, Element* aScroller)
|
|||
RegisterWithScrollSource();
|
||||
}
|
||||
|
||||
Nullable<TimeDuration> ScrollTimeline::GetCurrentTimeAsDuration() const {
|
||||
const nsIFrame* frame = nsLayoutUtils::GetScrollFrameFromContent(mSource);
|
||||
const nsIScrollableFrame* scrollFrame =
|
||||
frame ? frame->GetScrollTargetFrame() : nullptr;
|
||||
if (!scrollFrame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto orientation = GetPhysicalOrientation(frame->GetWritingMode());
|
||||
// If this orientation is not ready for scrolling (i.e. the scroll range is
|
||||
// not larger than or equal to one device pixel), we make it 100%.
|
||||
if (!scrollFrame->GetAvailableScrollingDirections().contains(orientation)) {
|
||||
return TimeDuration::FromMilliseconds(SCROLL_TIMELINE_DURATION_MILLISEC);
|
||||
}
|
||||
|
||||
const nsPoint& scrollOffset = scrollFrame->GetScrollPosition();
|
||||
const nsRect& scrollRange = scrollFrame->GetScrollRange();
|
||||
const bool isHorizontal = orientation == layers::ScrollDirection::eHorizontal;
|
||||
|
||||
// Note: For RTL, scrollOffset.x or scrollOffset.y may be negative, e.g. the
|
||||
// range of its value is [0, -range], so we have to use the absolute value.
|
||||
double position = std::abs(isHorizontal ? scrollOffset.x : scrollOffset.y);
|
||||
double range = isHorizontal ? scrollRange.width : scrollRange.height;
|
||||
MOZ_ASSERT(range > 0.0);
|
||||
// Use the definition of interval progress to compute the progress.
|
||||
// Note: We simplify the scroll offsets to [0%, 100%], so offset weight and
|
||||
// offset index are ignored here.
|
||||
// https://drafts.csswg.org/scroll-animations-1/#progress-calculation-algorithm
|
||||
double progress = position / range;
|
||||
return TimeDuration::FromMilliseconds(progress *
|
||||
SCROLL_TIMELINE_DURATION_MILLISEC);
|
||||
}
|
||||
|
||||
void ScrollTimeline::RegisterWithScrollSource() {
|
||||
if (!mSource) {
|
||||
return;
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include "mozilla/dom/AnimationTimeline.h"
|
||||
#include "mozilla/HashTable.h"
|
||||
#include "mozilla/ServoStyleConsts.h"
|
||||
#include "mozilla/TimingParams.h"
|
||||
#include "mozilla/WritingModes.h"
|
||||
|
||||
#define SCROLL_TIMELINE_DURATION_MILLISEC 100000
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -71,10 +75,7 @@ class ScrollTimeline final : public AnimationTimeline {
|
|||
}
|
||||
|
||||
// AnimationTimeline methods.
|
||||
Nullable<TimeDuration> GetCurrentTimeAsDuration() const override {
|
||||
// FIXME: We will update this function in the patch series.
|
||||
return nullptr;
|
||||
}
|
||||
Nullable<TimeDuration> GetCurrentTimeAsDuration() const override;
|
||||
bool TracksWallclockTime() const override { return false; }
|
||||
Nullable<TimeDuration> ToTimelineTime(
|
||||
const TimeStamp& aTimeStamp) const override {
|
||||
|
@ -88,6 +89,7 @@ class ScrollTimeline final : public AnimationTimeline {
|
|||
return {};
|
||||
}
|
||||
Document* GetDocument() const override { return mDocument; }
|
||||
bool IsScrollTimeline() const override { return true; }
|
||||
|
||||
void ScheduleAnimations() {
|
||||
// FIXME: Bug 1737927: Need to check the animation mutation observers for
|
||||
|
@ -97,6 +99,19 @@ class ScrollTimeline final : public AnimationTimeline {
|
|||
Tick();
|
||||
}
|
||||
|
||||
static const TimingParams& GetTiming() {
|
||||
// Use default values except for mDuration and mFill.
|
||||
// Use a fixed duration defined in SCROLL_TIMELINE_DURATIONMILLISEC, and use
|
||||
// FillMode::Both to make sure the animation is in effect at 100%.
|
||||
// Note: it's unfortunate TimingParams cannot be a const variable because
|
||||
// we have to use StickyTimingDuration::FromMilliseconds() in its
|
||||
// constructor.
|
||||
static TimingParams sTiming =
|
||||
TimingParams(SCROLL_TIMELINE_DURATION_MILLISEC, 0.0, 1.0,
|
||||
PlaybackDirection::Normal, FillMode::Both);
|
||||
return sTiming;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~ScrollTimeline() { Teardown(); }
|
||||
|
||||
|
@ -110,7 +125,31 @@ class ScrollTimeline final : public AnimationTimeline {
|
|||
void RegisterWithScrollSource();
|
||||
void UnregisterFromScrollSource();
|
||||
|
||||
// A helper to get the physical orientation of this scroll-timeline.
|
||||
//
|
||||
// The spec defines auto, but there is a spec issue:
|
||||
// "ISSUE 5 Define these values." in this section. The DOM interface removed
|
||||
// auto and use block as default value, so we treat auto as block now.
|
||||
// https://drafts.csswg.org/scroll-animations-1/#descdef-scroll-timeline-orientation
|
||||
layers::ScrollDirection GetPhysicalOrientation(WritingMode aWM) const {
|
||||
return mDirection == StyleScrollDirection::Horizontal ||
|
||||
(!aWM.IsVertical() &&
|
||||
mDirection == StyleScrollDirection::Inline) ||
|
||||
(aWM.IsVertical() &&
|
||||
(mDirection == StyleScrollDirection::Block ||
|
||||
mDirection == StyleScrollDirection::Auto))
|
||||
? layers::ScrollDirection::eHorizontal
|
||||
: layers::ScrollDirection::eVertical;
|
||||
}
|
||||
|
||||
RefPtr<Document> mDocument;
|
||||
|
||||
// FIXME: Bug 1733260: new spec proposal uses a new way to define scroller,
|
||||
// and move the element-based offset into view-timeline, so here we only
|
||||
// implement the default behavior of scroll timeline:
|
||||
// 1. "source" is auto (use main viewport scroller), and
|
||||
// 2. "scroll-offsets" is none (i.e. always 0% ~ 100%).
|
||||
// So now we will only use the scroll direction from @scroll-timeline rule.
|
||||
RefPtr<Element> mSource;
|
||||
StyleScrollDirection mDirection;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче