Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Unified Diff: third_party/WebKit/Source/core/animation/ScrollTimeline.cpp

Issue 2873493002: Basic ScrollTimeline implementation for Animation Worklet (Closed)
Patch Set: Add helper method in tests for creating options Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
diff --git a/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..63472fcbeb811d9c11c6a19b79529f4b8fb7c623
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
@@ -0,0 +1,179 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/animation/ScrollTimeline.h"
+
+#include "core/dom/ExceptionCode.h"
+#include "core/layout/LayoutBox.h"
+#include "core/paint/PaintLayerScrollableArea.h"
+
+namespace blink {
+
+namespace {
+bool StringToScrollDirection(String scroll_direction,
+ ScrollTimeline::ScrollDirection* result) {
+ if (scroll_direction == "auto") {
+ *result = ScrollTimeline::Auto;
+ return true;
+ }
+ if (scroll_direction == "block") {
+ *result = ScrollTimeline::Block;
+ return true;
+ }
+ if (scroll_direction == "inline") {
+ *result = ScrollTimeline::Inline;
+ return true;
+ }
+ return false;
+}
+} // namespace
+
+ScrollTimeline* ScrollTimeline::Create(const Document& document,
+ ScrollTimelineOptions options,
+ ExceptionState& exception_state) {
+ Element* scroll_source =
+ options.scrollSource()
+ ? options.scrollSource()
+ : const_cast<Document&>(document).scrollingElement();
majidvp 2017/05/17 20:39:45 I believe this should instead use |ScrollingElemen
majidvp 2017/05/17 20:39:45 It is odd that this method is not |const| requirin
smcgruer 2017/05/18 13:58:56 My only concern here is that |scrollingElement()|
smcgruer 2017/05/18 14:17:21 Turns out that the Document& doesnt have to be con
+
+ ScrollDirection orientation;
+ if (!StringToScrollDirection(options.orientation(), &orientation)) {
+ exception_state.ThrowDOMException(kNotSupportedError,
+ "Invalid orientation");
+ return nullptr;
+ }
+
+ // TODO(smcgruer): Support 'auto' value.
+ if (options.timeRange().isScrollTimelineAutoKeyword()) {
+ exception_state.ThrowDOMException(
+ kNotSupportedError, "'auto' value for timeRange not yet supported");
+ return nullptr;
+ }
+
+ return new ScrollTimeline(document, scroll_source, orientation,
+ options.timeRange().getAsDouble());
+}
+
+ScrollTimeline::ScrollTimeline(const Document& document,
+ Element* scroll_source,
+ ScrollDirection orientation,
+ double time_range)
+ : AnimationTimeline(const_cast<Document*>(&document), nullptr),
+ scroll_source_(scroll_source),
+ orientation_(orientation),
+ time_range_(time_range) {}
+
+double ScrollTimeline::currentTime(bool& is_null) {
+ // 1. If scrollSource does not currently have a CSS layout box, or if its
+ // layout box is not a scroll container, return an unresolved time value.
+ LayoutBox* layout_box = scroll_source_->GetLayoutBox();
+ if (!layout_box || !layout_box->HasOverflowClip()) {
+ is_null = true;
+ return std::numeric_limits<double>::quiet_NaN();
+ }
+
+ // 2. Otherwise, let current scroll offset be the current scroll offset of
+ // scrollSource in the direction specified by orientation.
+
+ // 'auto' ScrollDirection is specified as: If only one direction is
+ // scrollable, selects that direction. Otherwise selects the direction along
+ // the block axis.
+ ScrollDirection local_orientation = orientation_;
+ bool is_horizontal = layout_box->IsHorizontalWritingMode();
+ if (local_orientation == Auto) {
+ if (layout_box->HasScrollableOverflowX() &&
+ !layout_box->HasScrollableOverflowY()) {
+ local_orientation = is_horizontal ? Inline : Block;
+ } else if (!layout_box->HasScrollableOverflowX() &&
+ layout_box->HasScrollableOverflowY()) {
+ local_orientation = is_horizontal ? Block : Inline;
+ } else {
+ // Either neither or both axes are scrollable, so select the block
+ // direction.
+ local_orientation = Block;
+ }
+ }
majidvp 2017/05/17 20:39:45 Should this decision be made every time we query c
smcgruer 2017/05/18 13:58:56 Filed https://github.com/WICG/scroll-animations/is
smcgruer 2017/05/23 14:47:27 https://github.com/WICG/scroll-animations/issues/1
+
+ // Depending on the writing-mode and direction, the scroll origin shifts and
+ // the scroll offset may be negative. The easiest way to deal with this is to
+ // use only the magnitude of the scroll offset, and compare it to (max-offset
+ // - min_offset).
+ PaintLayerScrollableArea* scrollable_area = layout_box->GetScrollableArea();
+ ScrollOffset abs_scroll_offset =
+ ScrollOffset(std::abs(scrollable_area->GetScrollOffset().Width()),
+ std::abs(scrollable_area->GetScrollOffset().Height()));
+ ScrollOffset max_abs_scroll_offset = scrollable_area->MaximumScrollOffset() -
majidvp 2017/05/17 20:39:45 nit: s/max_abs_scroll_offset/scroll_dimensions/ (
smcgruer 2017/05/18 13:58:56 Done.
+ scrollable_area->MinimumScrollOffset();
+
+ double current_offset;
+ double max_offset;
+ DCHECK(local_orientation == Block || local_orientation == Inline);
+ if (local_orientation == Block) {
+ current_offset =
+ is_horizontal ? abs_scroll_offset.Height() : abs_scroll_offset.Width();
+ max_offset = is_horizontal ? max_abs_scroll_offset.Height()
+ : max_abs_scroll_offset.Width();
+ } else {
+ current_offset =
+ is_horizontal ? abs_scroll_offset.Width() : abs_scroll_offset.Height();
+ max_offset = is_horizontal ? max_abs_scroll_offset.Width()
+ : max_abs_scroll_offset.Height();
+ }
+
+ // 3. If current scroll offset is less than startScrollOffset, return an
+ // unresolved time value if fill is none or forwards, or 0 otherwise.
+ // TODO(smcgruer): Implement |startScrollOffset| and |fill|.
+
+ // 4. If current scroll offset is greater than or equal to endScrollOffset,
+ // return an unresolved time value if fill is none or backwards, or the
+ // effective time range otherwise.
+ // TODO(smcgruer): Implement |endScrollOffset| and |fill|.
+
+ // 5. Return the result of evaluating the following expression:
+ // ((current scroll offset - startScrollOffset) /
+ // (endScrollOffset - startScrollOffset)) * effective time range
+
+ is_null = false;
+ return (current_offset / max_offset) * time_range_;
majidvp 2017/05/17 20:39:44 may be cleaner if we just move std::abs operation
smcgruer 2017/05/18 13:58:56 Done.
+}
+
+double ScrollTimeline::currentTime() {
+ bool ignored;
+ return currentTime(ignored);
+}
+
+double ScrollTimeline::CurrentTimeInternal(bool& is_null) {
+ return currentTime(is_null);
+}
+
+double ScrollTimeline::CurrentTimeInternal() {
+ bool ignored;
+ return currentTime(ignored);
+}
+
+Element* ScrollTimeline::scrollSource() {
+ return scroll_source_.Get();
+}
+
+String ScrollTimeline::orientation() {
+ switch (orientation_) {
+ case Auto:
+ return "auto";
majidvp 2017/05/17 20:39:45 If we decide to resolve "auto" value on constructi
+ case Block:
+ return "block";
+ case Inline:
+ return "inline";
+ }
+}
+
+void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) {
+ result.setDouble(time_range_);
+}
+
+DEFINE_TRACE(ScrollTimeline) {
+ visitor->Trace(scroll_source_);
+ AnimationTimeline::Trace(visitor);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698