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 // TODO(smcgruer): The spec allows for a null scrollSource. | |
majidvp
2017/05/15 14:38:52
Hmmm, I presume that if the scrollSource is not sp
smcgruer
2017/05/15 15:22:54
Nope, spec defines it as follows (https://wicg.git
flackr
2017/05/15 17:29:06
Note, probably should be the document.scrollingEle
smcgruer
2017/05/16 19:24:47
Filed https://github.com/WICG/scroll-animations/is
| |
36 if (!options.scrollSource()) { | |
37 exception_state.ThrowDOMException(kNotSupportedError, | |
38 "A scrollSource must be specified"); | |
39 return nullptr; | |
40 } | |
41 | |
42 ScrollDirection orientation; | |
43 if (!StringToScrollDirection(options.orientation(), &orientation)) { | |
44 exception_state.ThrowDOMException(kNotSupportedError, | |
45 "Invalid orientation"); | |
46 return nullptr; | |
47 } | |
48 | |
49 // TODO(smcgruer): Support 'auto' value. | |
50 if (options.timeRange().isScrollTimelineAutoKeyword()) { | |
51 exception_state.ThrowDOMException( | |
52 kNotSupportedError, "'auto' value for timeRange not yet supported"); | |
53 } | |
54 | |
55 return new ScrollTimeline(document, options.scrollSource(), orientation, | |
56 options.timeRange().getAsDouble()); | |
57 } | |
58 | |
59 ScrollTimeline::ScrollTimeline(const Document& document, | |
60 Element* scroll_source, | |
61 ScrollDirection orientation, | |
62 double time_range) | |
63 : AnimationTimeline(const_cast<Document*>(&document), nullptr), | |
64 scroll_source_(scroll_source), | |
65 orientation_(orientation), | |
66 time_range_(time_range) {} | |
67 | |
68 double ScrollTimeline::currentTime(bool& is_null) { | |
69 // 1. If scrollSource does not currently have a CSS layout box, or if its | |
70 // layout box is not a scroll container, return an unresolved time value. | |
71 LayoutBox* layout_box = scroll_source_->GetLayoutBox(); | |
72 if (!layout_box || !layout_box->GetScrollableArea()) { | |
majidvp
2017/05/15 14:38:52
I don't think layout_box->GetScrollableArea() maps
smcgruer
2017/05/15 15:22:54
Ah, so looks like by the spec we just want to chec
flackr
2017/05/15 17:29:06
LayoutObject::HasOverflowClip
smcgruer
2017/05/16 19:24:47
Done.
| |
73 LOG(INFO) << "!layout_box || !layout_box->GetScrollableArea()"; | |
74 is_null = true; | |
75 return std::numeric_limits<double>::quiet_NaN(); | |
76 } | |
77 | |
78 // 2. Otherwise, let current scroll offset be the current scroll offset of | |
79 // scrollSource in the direction specified by orientation. | |
80 ScrollDirection local_orientation = orientation_; | |
81 if (local_orientation == Auto) { | |
82 // If only one direction is scrollable, selects that direction. Otherwise | |
83 // selects the direction along the block axis. | |
84 DCHECK(layout_box->HasScrollableOverflowX() || | |
85 layout_box->HasScrollableOverflowY()); | |
flackr
2017/05/15 17:29:06
I don't think this check is correct. We could have
smcgruer
2017/05/17 15:52:03
Done.
| |
86 local_orientation = layout_box->HasScrollableOverflowY() ? Block : Inline; | |
flackr
2017/05/15 17:29:06
Isn't this assuming LTR? I think you'd have to che
smcgruer
2017/05/17 15:52:02
Done.
| |
87 } | |
88 double current_scroll_offset = 0.0; | |
89 double max_scroll_offset = 1.0; | |
90 switch (local_orientation) { | |
91 case Block: | |
92 current_scroll_offset = scroll_source_->scrollTop(); | |
93 max_scroll_offset = | |
94 scroll_source_->scrollHeight() - scroll_source_->clientHeight(); | |
majidvp
2017/05/15 14:38:52
Shouldn't we use the logical coordinates here as o
smcgruer
2017/05/15 15:22:54
Possibly. I just wrote this based on a comment in
smcgruer
2017/05/17 15:52:02
Done.
| |
95 break; | |
96 case Inline: | |
97 current_scroll_offset = scroll_source_->scrollLeft(); | |
98 max_scroll_offset = | |
99 scroll_source_->scrollWidth() - scroll_source_->clientWidth(); | |
100 break; | |
101 case Auto: | |
102 LOG(FATAL) << "local_orientation cannot be Auto"; | |
103 break; | |
104 } | |
105 | |
106 // 3. If current scroll offset is less than startScrollOffset, return an | |
107 // unresolved time value if fill is none or forwards, or 0 otherwise. | |
108 // TODO(smcgruer): Implement |startScrollOffset| and |fill|. | |
109 | |
110 // 4. If current scroll offset is greater than or equal to endScrollOffset, | |
111 // return an unresolved time value if fill is none or backwards, or the | |
112 // effective time range otherwise. | |
113 // TODO(smcgruer): Implement |endScrollOffset| and |fill|. | |
114 | |
115 // 5. Return the result of evaluating the following expression: | |
116 // ((current scroll offset - startScrollOffset) / | |
117 // (endScrollOffset - startScrollOffset)) * effective time range | |
118 | |
119 is_null = false; | |
120 return (current_scroll_offset / max_scroll_offset) * time_range_; | |
121 } | |
122 | |
123 double ScrollTimeline::currentTime() { | |
124 bool ignored; | |
125 return currentTime(ignored); | |
126 } | |
127 | |
128 double ScrollTimeline::CurrentTimeInternal(bool& is_null) { | |
129 return currentTime(is_null); | |
130 } | |
131 | |
132 double ScrollTimeline::CurrentTimeInternal() { | |
133 bool ignored; | |
134 return currentTime(ignored); | |
135 } | |
136 | |
137 Element* ScrollTimeline::scrollSource() { | |
138 return scroll_source_.Get(); | |
139 } | |
140 | |
141 String ScrollTimeline::orientation() { | |
142 switch (orientation_) { | |
143 case Auto: | |
144 return "auto"; | |
145 case Block: | |
146 return "block"; | |
147 case Inline: | |
148 return "inline"; | |
149 } | |
150 } | |
151 | |
152 void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) { | |
153 result.setDouble(time_range_); | |
154 } | |
155 | |
156 DEFINE_TRACE(ScrollTimeline) { | |
157 visitor->Trace(scroll_source_); | |
158 AnimationTimeline::Trace(visitor); | |
159 } | |
160 | |
161 } // namespace blink | |
OLD | NEW |