OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "core/animation/ScrollTimeline.h" | |
6 | |
7 #include "core/dom/ExceptionCode.h" | |
8 #include "core/layout/LayoutBox.h" | |
9 #include "core/paint/PaintLayerScrollableArea.h" | |
10 | |
11 namespace blink { | |
12 | |
13 namespace { | |
14 bool StringToScrollDirection(String scroll_direction, | |
15 ScrollTimeline::ScrollDirection* result) { | |
16 if (scroll_direction == "auto") { | |
17 *result = ScrollTimeline::Auto; | |
18 return true; | |
19 } | |
20 if (scroll_direction == "block") { | |
21 *result = ScrollTimeline::Block; | |
22 return true; | |
23 } | |
24 if (scroll_direction == "inline") { | |
25 *result = ScrollTimeline::Inline; | |
26 return true; | |
27 } | |
28 return false; | |
29 } | |
30 } // namespace | |
31 | |
32 ScrollTimeline* ScrollTimeline::Create(const Document& document, | |
33 ScrollTimelineOptions options, | |
34 ExceptionState& exception_state) { | |
35 Element* scroll_source = | |
36 options.scrollSource() | |
37 ? options.scrollSource() | |
38 : 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
| |
39 | |
40 ScrollDirection orientation; | |
41 if (!StringToScrollDirection(options.orientation(), &orientation)) { | |
42 exception_state.ThrowDOMException(kNotSupportedError, | |
43 "Invalid orientation"); | |
44 return nullptr; | |
45 } | |
46 | |
47 // TODO(smcgruer): Support 'auto' value. | |
48 if (options.timeRange().isScrollTimelineAutoKeyword()) { | |
49 exception_state.ThrowDOMException( | |
50 kNotSupportedError, "'auto' value for timeRange not yet supported"); | |
51 return nullptr; | |
52 } | |
53 | |
54 return new ScrollTimeline(document, scroll_source, orientation, | |
55 options.timeRange().getAsDouble()); | |
56 } | |
57 | |
58 ScrollTimeline::ScrollTimeline(const Document& document, | |
59 Element* scroll_source, | |
60 ScrollDirection orientation, | |
61 double time_range) | |
62 : AnimationTimeline(const_cast<Document*>(&document), nullptr), | |
63 scroll_source_(scroll_source), | |
64 orientation_(orientation), | |
65 time_range_(time_range) {} | |
66 | |
67 double ScrollTimeline::currentTime(bool& is_null) { | |
68 // 1. If scrollSource does not currently have a CSS layout box, or if its | |
69 // layout box is not a scroll container, return an unresolved time value. | |
70 LayoutBox* layout_box = scroll_source_->GetLayoutBox(); | |
71 if (!layout_box || !layout_box->HasOverflowClip()) { | |
72 is_null = true; | |
73 return std::numeric_limits<double>::quiet_NaN(); | |
74 } | |
75 | |
76 // 2. Otherwise, let current scroll offset be the current scroll offset of | |
77 // scrollSource in the direction specified by orientation. | |
78 | |
79 // 'auto' ScrollDirection is specified as: If only one direction is | |
80 // scrollable, selects that direction. Otherwise selects the direction along | |
81 // the block axis. | |
82 ScrollDirection local_orientation = orientation_; | |
83 bool is_horizontal = layout_box->IsHorizontalWritingMode(); | |
84 if (local_orientation == Auto) { | |
85 if (layout_box->HasScrollableOverflowX() && | |
86 !layout_box->HasScrollableOverflowY()) { | |
87 local_orientation = is_horizontal ? Inline : Block; | |
88 } else if (!layout_box->HasScrollableOverflowX() && | |
89 layout_box->HasScrollableOverflowY()) { | |
90 local_orientation = is_horizontal ? Block : Inline; | |
91 } else { | |
92 // Either neither or both axes are scrollable, so select the block | |
93 // direction. | |
94 local_orientation = Block; | |
95 } | |
96 } | |
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
| |
97 | |
98 // Depending on the writing-mode and direction, the scroll origin shifts and | |
99 // the scroll offset may be negative. The easiest way to deal with this is to | |
100 // use only the magnitude of the scroll offset, and compare it to (max-offset | |
101 // - min_offset). | |
102 PaintLayerScrollableArea* scrollable_area = layout_box->GetScrollableArea(); | |
103 ScrollOffset abs_scroll_offset = | |
104 ScrollOffset(std::abs(scrollable_area->GetScrollOffset().Width()), | |
105 std::abs(scrollable_area->GetScrollOffset().Height())); | |
106 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.
| |
107 scrollable_area->MinimumScrollOffset(); | |
108 | |
109 double current_offset; | |
110 double max_offset; | |
111 DCHECK(local_orientation == Block || local_orientation == Inline); | |
112 if (local_orientation == Block) { | |
113 current_offset = | |
114 is_horizontal ? abs_scroll_offset.Height() : abs_scroll_offset.Width(); | |
115 max_offset = is_horizontal ? max_abs_scroll_offset.Height() | |
116 : max_abs_scroll_offset.Width(); | |
117 } else { | |
118 current_offset = | |
119 is_horizontal ? abs_scroll_offset.Width() : abs_scroll_offset.Height(); | |
120 max_offset = is_horizontal ? max_abs_scroll_offset.Width() | |
121 : max_abs_scroll_offset.Height(); | |
122 } | |
123 | |
124 // 3. If current scroll offset is less than startScrollOffset, return an | |
125 // unresolved time value if fill is none or forwards, or 0 otherwise. | |
126 // TODO(smcgruer): Implement |startScrollOffset| and |fill|. | |
127 | |
128 // 4. If current scroll offset is greater than or equal to endScrollOffset, | |
129 // return an unresolved time value if fill is none or backwards, or the | |
130 // effective time range otherwise. | |
131 // TODO(smcgruer): Implement |endScrollOffset| and |fill|. | |
132 | |
133 // 5. Return the result of evaluating the following expression: | |
134 // ((current scroll offset - startScrollOffset) / | |
135 // (endScrollOffset - startScrollOffset)) * effective time range | |
136 | |
137 is_null = false; | |
138 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.
| |
139 } | |
140 | |
141 double ScrollTimeline::currentTime() { | |
142 bool ignored; | |
143 return currentTime(ignored); | |
144 } | |
145 | |
146 double ScrollTimeline::CurrentTimeInternal(bool& is_null) { | |
147 return currentTime(is_null); | |
148 } | |
149 | |
150 double ScrollTimeline::CurrentTimeInternal() { | |
151 bool ignored; | |
152 return currentTime(ignored); | |
153 } | |
154 | |
155 Element* ScrollTimeline::scrollSource() { | |
156 return scroll_source_.Get(); | |
157 } | |
158 | |
159 String ScrollTimeline::orientation() { | |
160 switch (orientation_) { | |
161 case Auto: | |
162 return "auto"; | |
majidvp
2017/05/17 20:39:45
If we decide to resolve "auto" value on constructi
| |
163 case Block: | |
164 return "block"; | |
165 case Inline: | |
166 return "inline"; | |
167 } | |
168 } | |
169 | |
170 void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) { | |
171 result.setDouble(time_range_); | |
172 } | |
173 | |
174 DEFINE_TRACE(ScrollTimeline) { | |
175 visitor->Trace(scroll_source_); | |
176 AnimationTimeline::Trace(visitor); | |
177 } | |
178 | |
179 } // namespace blink | |
OLD | NEW |