зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1676791 - Part 5: Define the finite timeline and use it in Play() and Pause(). r=hiro
Based on https://github.com/w3c/csswg-drafts/pull/4842, we define "has finite timeline", which is a timeline that's not monotonically increasing. We need this to update start time and hold time for scroll-timeline, so we play scroll-linked animations as we expected, e.g. GetLocalTime() returns the correct time value from GetCurrentTimeAsDuration(). Known issue: we still have bugs when setting "animation-play-state:paused". Will do that in Bug 1741255. Differential Revision: https://phabricator.services.mozilla.com/D131168
This commit is contained in:
Родитель
7ea5fa0013
Коммит
fcbeb1d2b0
|
@ -493,7 +493,7 @@ void Animation::UpdatePlaybackRate(double aPlaybackRate) {
|
|||
// https://drafts.csswg.org/web-animations/#play-state
|
||||
AnimationPlayState Animation::PlayState() const {
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTimeAsDuration();
|
||||
if (currentTime.IsNull() && !Pending()) {
|
||||
if (currentTime.IsNull() && mStartTime.IsNull() && !Pending()) {
|
||||
return AnimationPlayState::Idle;
|
||||
}
|
||||
|
||||
|
@ -1350,15 +1350,15 @@ void Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior) {
|
|||
AutoMutationBatchForAnimation mb(*this);
|
||||
|
||||
bool abortedPause = mPendingState == PendingState::PausePending;
|
||||
|
||||
double effectivePlaybackRate = CurrentOrPendingPlaybackRate();
|
||||
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTimeAsDuration();
|
||||
Nullable<TimeDuration> seekTime;
|
||||
if (effectivePlaybackRate > 0.0 &&
|
||||
(currentTime.IsNull() || (aLimitBehavior == LimitBehavior::AutoRewind &&
|
||||
(currentTime.Value() < TimeDuration() ||
|
||||
currentTime.Value() >= EffectEnd())))) {
|
||||
mHoldTime.SetValue(TimeDuration(0));
|
||||
seekTime.SetValue(TimeDuration(0));
|
||||
} else if (effectivePlaybackRate < 0.0 &&
|
||||
(currentTime.IsNull() ||
|
||||
(aLimitBehavior == LimitBehavior::AutoRewind &&
|
||||
|
@ -1368,9 +1368,19 @@ void Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior) {
|
|||
return aRv.ThrowInvalidStateError(
|
||||
"Can't rewind animation with infinite effect end");
|
||||
}
|
||||
mHoldTime.SetValue(TimeDuration(EffectEnd()));
|
||||
seekTime.SetValue(TimeDuration(EffectEnd()));
|
||||
} else if (effectivePlaybackRate == 0.0 && currentTime.IsNull()) {
|
||||
mHoldTime.SetValue(TimeDuration(0));
|
||||
seekTime.SetValue(TimeDuration(0));
|
||||
}
|
||||
|
||||
if (!seekTime.IsNull()) {
|
||||
if (HasFiniteTimeline()) {
|
||||
mStartTime = seekTime;
|
||||
mHoldTime.SetNull();
|
||||
ApplyPendingPlaybackRate();
|
||||
} else {
|
||||
mHoldTime = seekTime;
|
||||
}
|
||||
}
|
||||
|
||||
bool reuseReadyPromise = false;
|
||||
|
@ -1390,7 +1400,8 @@ void Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior) {
|
|||
// (b) If we have timing changes (specifically a change to the playbackRate)
|
||||
// that should be applied asynchronously.
|
||||
//
|
||||
if (mHoldTime.IsNull() && !abortedPause && !mPendingPlaybackRate) {
|
||||
if (mHoldTime.IsNull() && seekTime.IsNull() && !abortedPause &&
|
||||
!mPendingPlaybackRate) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1443,15 +1454,24 @@ void Animation::Pause(ErrorResult& aRv) {
|
|||
|
||||
AutoMutationBatchForAnimation mb(*this);
|
||||
|
||||
Nullable<TimeDuration> seekTime;
|
||||
// If we are transitioning from idle, fill in the current time
|
||||
if (GetCurrentTimeAsDuration().IsNull()) {
|
||||
if (mPlaybackRate >= 0.0) {
|
||||
mHoldTime.SetValue(TimeDuration(0));
|
||||
seekTime.SetValue(TimeDuration(0));
|
||||
} else {
|
||||
if (EffectEnd() == TimeDuration::Forever()) {
|
||||
return aRv.ThrowInvalidStateError("Can't seek to infinite effect end");
|
||||
}
|
||||
mHoldTime.SetValue(TimeDuration(EffectEnd()));
|
||||
seekTime.SetValue(TimeDuration(EffectEnd()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!seekTime.IsNull()) {
|
||||
if (HasFiniteTimeline()) {
|
||||
mStartTime = seekTime;
|
||||
} else {
|
||||
mHoldTime = seekTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -557,6 +557,10 @@ class Animation : public DOMEventTargetHelper,
|
|||
Document* GetRenderedDocument() const;
|
||||
Document* GetTimelineDocument() const;
|
||||
|
||||
bool HasFiniteTimeline() const {
|
||||
return mTimeline && !mTimeline->IsMonotonicallyIncreasing();
|
||||
}
|
||||
|
||||
RefPtr<AnimationTimeline> mTimeline;
|
||||
RefPtr<AnimationEffect> mEffect;
|
||||
// The beginning of the delay period.
|
||||
|
|
|
@ -101,6 +101,8 @@ class AnimationTimeline : public nsISupports, public nsWrapperCache {
|
|||
|
||||
virtual Document* GetDocument() const = 0;
|
||||
|
||||
virtual bool IsMonotonicallyIncreasing() const = 0;
|
||||
|
||||
virtual bool IsScrollTimeline() const { return false; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -68,6 +68,8 @@ class DocumentTimeline final : public AnimationTimeline,
|
|||
|
||||
Document* GetDocument() const override { return mDocument; }
|
||||
|
||||
bool IsMonotonicallyIncreasing() const override { return true; }
|
||||
|
||||
protected:
|
||||
TimeStamp GetCurrentTimeStamp() const;
|
||||
nsRefreshDriver* GetRefreshDriver() const;
|
||||
|
|
|
@ -87,6 +87,7 @@ class ScrollTimeline final : public AnimationTimeline {
|
|||
return {};
|
||||
}
|
||||
Document* GetDocument() const override { return mDocument; }
|
||||
bool IsMonotonicallyIncreasing() const override { return false; }
|
||||
bool IsScrollTimeline() const override { return true; }
|
||||
|
||||
void ScheduleAnimations() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче