blob: 083c4cf594d80bf331b6c4243b9e2e32af46f531 [file] [log] [blame]
Stephen McGruer26390b32018-12-10 15:47:181<!DOCTYPE html>
2<meta charset="utf-8">
3<title>ScrollTimeline current time algorithm - interaction with writing modes</title>
4<link rel="help" href="https://wicg.github.io/scroll-animations/#current-time-algorithm">
5<script src="/resources/testharness.js"></script>
6<script src="/resources/testharnessreport.js"></script>
7
8<script src="./resources/scrolltimeline-utils.js"></script>
9
10<body></body>
11
12<script>
13'use strict';
14
15test(function() {
16 const scrollerOverrides = new Map([['direction', 'rtl']]);
17 const scroller = setupScrollTimelineTest(scrollerOverrides);
18
19 // Set the timeRange such that currentTime maps directly to the value
20 // scrolled. The contents and scroller are square, so it suffices to compute
21 // one edge and use it for all the timelines.
22 const scrollerSize = scroller.scrollHeight - scroller.clientHeight;
23
24 const blockScrollTimeline = new ScrollTimeline(
25 {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'});
26 const inlineScrollTimeline = new ScrollTimeline(
27 {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'});
28 const horizontalScrollTimeline = new ScrollTimeline({
29 scrollSource: scroller,
30 timeRange: scrollerSize,
31 orientation: 'horizontal'
32 });
33 const verticalScrollTimeline = new ScrollTimeline({
34 scrollSource: scroller,
35 timeRange: scrollerSize,
36 orientation: 'vertical'
37 });
38
39 // Unscrolled, all timelines should read a current time of 0 even though the
40 // X-axis will have started at the right hand side for rtl.
41 assert_equals(
42 blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline');
43 assert_equals(
44 inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline');
45 assert_equals(
46 horizontalScrollTimeline.currentTime, 0,
47 'Unscrolled horizontal timeline');
48 assert_equals(
49 verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline');
50
51 // The offset in the inline/horizontal direction should be inverted. The
52 // block/vertical direction should be unaffected.
53 scroller.scrollTop = 50;
Cathie Chen30018932019-10-10 03:10:3154 scroller.scrollLeft = 75 - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:1855
56 assert_equals(blockScrollTimeline.currentTime, 50, 'Scrolled block timeline');
57 assert_equals(
58 inlineScrollTimeline.currentTime, scrollerSize - 75,
59 'Scrolled inline timeline');
60 assert_equals(
61 horizontalScrollTimeline.currentTime, scrollerSize - 75,
62 'Scrolled horizontal timeline');
63 assert_equals(
64 verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline');
65}, 'currentTime handles direction: rtl correctly');
66
67test(function() {
68 const scrollerOverrides = new Map([['writing-mode', 'vertical-rl']]);
69 const scroller = setupScrollTimelineTest(scrollerOverrides);
70
71 // Set the timeRange such that currentTime maps directly to the value
72 // scrolled. The contents and scroller are square, so it suffices to compute
73 // one edge and use it for all the timelines.
74 const scrollerSize = scroller.scrollHeight - scroller.clientHeight;
75
76 const blockScrollTimeline = new ScrollTimeline(
77 {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'});
78 const inlineScrollTimeline = new ScrollTimeline(
79 {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'});
80 const horizontalScrollTimeline = new ScrollTimeline({
81 scrollSource: scroller,
82 timeRange: scrollerSize,
83 orientation: 'horizontal'
84 });
85 const verticalScrollTimeline = new ScrollTimeline({
86 scrollSource: scroller,
87 timeRange: scrollerSize,
88 orientation: 'vertical'
89 });
90
91 // Unscrolled, all timelines should read a current time of 0 even though the
92 // X-axis will have started at the right hand side for vertical-rl.
93 assert_equals(
94 blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline');
95 assert_equals(
96 inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline');
97 assert_equals(
98 horizontalScrollTimeline.currentTime, 0,
99 'Unscrolled horizontal timeline');
100 assert_equals(
101 verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline');
102
103 // For vertical-rl, the X-axis starts on the right-hand-side and is the block
104 // axis. The Y-axis is normal but is the inline axis. For the
105 // horizontal/vertical cases, horizontal starts on the right-hand-side and
106 // vertical is normal.
107 scroller.scrollTop = 50;
Cathie Chen30018932019-10-10 03:10:31108 scroller.scrollLeft = 75 - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18109
110 assert_equals(
111 blockScrollTimeline.currentTime, scrollerSize - 75,
112 'Scrolled block timeline');
113 assert_equals(
114 inlineScrollTimeline.currentTime, 50, 'SCrolled inline timeline');
115 assert_equals(
116 horizontalScrollTimeline.currentTime, scrollerSize - 75,
117 'Scrolled horizontal timeline');
118 assert_equals(
119 verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline');
120}, 'currentTime handles writing-mode: vertical-rl correctly');
121
122test(function() {
123 const scrollerOverrides = new Map([['writing-mode', 'vertical-lr']]);
124 const scroller = setupScrollTimelineTest(scrollerOverrides);
125
126 // Set the timeRange such that currentTime maps directly to the value
127 // scrolled. The contents and scroller are square, so it suffices to compute
128 // one edge and use it for all the timelines.
129 const scrollerSize = scroller.scrollHeight - scroller.clientHeight;
130
131 const blockScrollTimeline = new ScrollTimeline(
132 {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'});
133 const inlineScrollTimeline = new ScrollTimeline(
134 {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'});
135 const horizontalScrollTimeline = new ScrollTimeline({
136 scrollSource: scroller,
137 timeRange: scrollerSize,
138 orientation: 'horizontal'
139 });
140 const verticalScrollTimeline = new ScrollTimeline({
141 scrollSource: scroller,
142 timeRange: scrollerSize,
143 orientation: 'vertical'
144 });
145
146 // Unscrolled, all timelines should read a current time of 0.
147 assert_equals(
148 blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline');
149 assert_equals(
150 inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline');
151 assert_equals(
152 horizontalScrollTimeline.currentTime, 0,
153 'Unscrolled horizontal timeline');
154 assert_equals(
155 verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline');
156
157 // For vertical-lr, both axes start at their 'normal' positions but the X-axis
158 // is the block direction and the Y-axis is the inline direction. This does
159 // not affect horizontal/vertical.
160 scroller.scrollTop = 50;
161 scroller.scrollLeft = 75;
162
163 assert_equals(blockScrollTimeline.currentTime, 75, 'Scrolled block timeline');
164 assert_equals(
165 inlineScrollTimeline.currentTime, 50, 'Scrolled inline timeline');
166 assert_equals(
167 horizontalScrollTimeline.currentTime, 75, 'Scrolled horizontal timeline');
168 assert_equals(
169 verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline');
170}, 'currentTime handles writing-mode: vertical-lr correctly');
171
172test(function() {
173 const scrollerOverrides = new Map([['direction', 'rtl']]);
174 const scroller = setupScrollTimelineTest(scrollerOverrides);
175 // Set the timeRange such that currentTime maps directly to the value
176 // scrolled. The contents and scroller are square, so it suffices to compute
177 // one edge and use it for all the timelines.
178 const scrollerSize = scroller.scrollHeight - scroller.clientHeight;
179
180 const lengthScrollTimeline = new ScrollTimeline({
181 scrollSource: scroller,
182 timeRange: scrollerSize,
183 orientation: 'horizontal',
184 startScrollOffset: '20px'
185 });
186 const percentageScrollTimeline = new ScrollTimeline({
187 scrollSource: scroller,
188 timeRange: scrollerSize,
189 orientation: 'horizontal',
190 startScrollOffset: '20%'
191 });
192 const calcScrollTimeline = new ScrollTimeline({
193 scrollSource: scroller,
194 timeRange: scrollerSize,
195 orientation: 'horizontal',
196 startScrollOffset: 'calc(20% - 5px)'
197 });
198
199 // Unscrolled, all timelines should read a current time of unresolved, since
200 // the current offset (0) will be less than the startScrollOffset.
201 assert_equals(
202 lengthScrollTimeline.currentTime, null,
203 'Unscrolled length-based timeline');
204 assert_equals(
205 percentageScrollTimeline.currentTime, null,
206 'Unscrolled percentage-based timeline');
207 assert_equals(
208 calcScrollTimeline.currentTime, null, 'Unscrolled calc-based timeline');
209
Cathie Chen30018932019-10-10 03:10:31210 // With direction rtl offsets are inverted, such that scrollLeft == 0
211 // is the 'zero' point for currentTime. However the
Stephen McGruer26390b32018-12-10 15:47:18212 // startScrollOffset is an absolute distance along the offset, so doesn't
213 // need adjusting.
214
215 // Check the length-based ScrollTimeline.
Cathie Chen30018932019-10-10 03:10:31216 scroller.scrollLeft = 0;
Stephen McGruer26390b32018-12-10 15:47:18217 assert_equals(
218 lengthScrollTimeline.currentTime, null,
219 'Length-based timeline before the startScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31220 scroller.scrollLeft = -20;
Stephen McGruer26390b32018-12-10 15:47:18221 assert_equals(
222 lengthScrollTimeline.currentTime, 0,
223 'Length-based timeline at the startScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31224 scroller.scrollLeft = -50;
Stephen McGruer26390b32018-12-10 15:47:18225 assert_equals(
226 lengthScrollTimeline.currentTime,
227 calculateCurrentTime(50, 20, scrollerSize, scrollerSize),
228 'Length-based timeline after the startScrollOffset point');
229
230 // Check the percentage-based ScrollTimeline.
Cathie Chen30018932019-10-10 03:10:31231 scroller.scrollLeft = -(0.19 * scrollerSize);
Stephen McGruer26390b32018-12-10 15:47:18232 assert_equals(
233 percentageScrollTimeline.currentTime, null,
234 'Percentage-based timeline before the startScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31235 scroller.scrollLeft = -(0.20 * scrollerSize);
Stephen McGruer26390b32018-12-10 15:47:18236 assert_equals(
237 percentageScrollTimeline.currentTime, 0,
238 'Percentage-based timeline at the startScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31239 scroller.scrollLeft = -(0.4 * scrollerSize);
Stephen McGruer26390b32018-12-10 15:47:18240 assert_equals(
241 percentageScrollTimeline.currentTime,
242 calculateCurrentTime(
243 0.4 * scrollerSize, 0.2 * scrollerSize, scrollerSize, scrollerSize),
244 'Percentage-based timeline after the startScrollOffset point');
245
246 // Check the calc-based ScrollTimeline.
Cathie Chen30018932019-10-10 03:10:31247 scroller.scrollLeft = -(0.2 * scrollerSize - 10);
Stephen McGruer26390b32018-12-10 15:47:18248 assert_equals(
249 calcScrollTimeline.currentTime, null,
250 'Calc-based timeline before the startScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31251 scroller.scrollLeft = -(0.2 * scrollerSize - 5);
Stephen McGruer26390b32018-12-10 15:47:18252 assert_equals(
253 calcScrollTimeline.currentTime, 0,
254 'Calc-based timeline at the startScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31255 scroller.scrollLeft = -(0.2 * scrollerSize);
Stephen McGruer26390b32018-12-10 15:47:18256 assert_equals(
257 calcScrollTimeline.currentTime,
258 calculateCurrentTime(
259 0.2 * scrollerSize, 0.2 * scrollerSize - 5, scrollerSize,
260 scrollerSize),
261 'Calc-based timeline after the startScrollOffset point');
262}, 'currentTime handles startScrollOffset with direction: rtl correctly');
263
264test(function() {
265 const scrollerOverrides = new Map([['direction', 'rtl']]);
266 const scroller = setupScrollTimelineTest(scrollerOverrides);
267 // Set the timeRange such that currentTime maps directly to the value
268 // scrolled. The contents and scroller are square, so it suffices to compute
269 // one edge and use it for all the timelines.
270 const scrollerSize = scroller.scrollHeight - scroller.clientHeight;
271
272 const lengthScrollTimeline = new ScrollTimeline({
273 scrollSource: scroller,
274 timeRange: scrollerSize,
275 orientation: 'horizontal',
276 endScrollOffset: (scrollerSize - 20) + 'px'
277 });
278 const percentageScrollTimeline = new ScrollTimeline({
279 scrollSource: scroller,
280 timeRange: scrollerSize,
281 orientation: 'horizontal',
282 endScrollOffset: '80%'
283 });
284 const calcScrollTimeline = new ScrollTimeline({
285 scrollSource: scroller,
286 timeRange: scrollerSize,
287 orientation: 'horizontal',
288 endScrollOffset: 'calc(80% + 5px)'
289 });
290
Cathie Chen30018932019-10-10 03:10:31291 // With direction rtl offsets are inverted, such that scrollLeft == 0
292 // is the 'zero' point for currentTime. However the
Stephen McGruer26390b32018-12-10 15:47:18293 // endScrollOffset is an absolute distance along the offset, so doesn't need
294 // adjusting.
295
296 // Check the length-based ScrollTimeline.
Cathie Chen30018932019-10-10 03:10:31297 scroller.scrollLeft = -scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18298 assert_equals(
299 lengthScrollTimeline.currentTime, null,
300 'Length-based timeline after the endScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31301 scroller.scrollLeft = 20 - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18302 assert_equals(
Stephen McGruerce50d582019-03-01 03:00:02303 lengthScrollTimeline.currentTime, null,
Stephen McGruer26390b32018-12-10 15:47:18304 'Length-based timeline at the endScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31305 scroller.scrollLeft = 50 - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18306 assert_equals(
307 lengthScrollTimeline.currentTime,
308 calculateCurrentTime(
309 scrollerSize - 50, 0, scrollerSize - 20, scrollerSize),
310 'Length-based timeline before the endScrollOffset point');
311
312 // Check the percentage-based ScrollTimeline.
Cathie Chen30018932019-10-10 03:10:31313 scroller.scrollLeft = 0.19 * scrollerSize - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18314 assert_equals(
315 percentageScrollTimeline.currentTime, null,
316 'Percentage-based timeline after the endScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31317 scroller.scrollLeft = 0.20 * scrollerSize - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18318 assert_equals(
Stephen McGruerce50d582019-03-01 03:00:02319 percentageScrollTimeline.currentTime, null,
Stephen McGruer26390b32018-12-10 15:47:18320 'Percentage-based timeline at the endScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31321 scroller.scrollLeft = 0.4 * scrollerSize - scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18322 assert_equals(
323 percentageScrollTimeline.currentTime,
324 calculateCurrentTime(
325 0.6 * scrollerSize, 0, 0.8 * scrollerSize, scrollerSize),
326 'Percentage-based timeline before the endScrollOffset point');
327
328 // Check the calc-based ScrollTimeline. 80% + 5px
Cathie Chen30018932019-10-10 03:10:31329 scroller.scrollLeft = -0.8 * scrollerSize - 10;
Stephen McGruer26390b32018-12-10 15:47:18330 assert_equals(
331 calcScrollTimeline.currentTime, null,
332 'Calc-based timeline after the endScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31333 scroller.scrollLeft = -0.8 * scrollerSize - 5;
Stephen McGruer26390b32018-12-10 15:47:18334 assert_equals(
Stephen McGruerce50d582019-03-01 03:00:02335 calcScrollTimeline.currentTime, null,
Stephen McGruer26390b32018-12-10 15:47:18336 'Calc-based timeline at the endScrollOffset point');
Cathie Chen30018932019-10-10 03:10:31337 scroller.scrollLeft = -0.8 * scrollerSize;
Stephen McGruer26390b32018-12-10 15:47:18338 assert_equals(
339 calcScrollTimeline.currentTime,
340 calculateCurrentTime(
341 0.8 * scrollerSize, 0, 0.8 * scrollerSize + 5, scrollerSize),
342 'Calc-based timeline before the endScrollOffset point');
343}, 'currentTime handles endScrollOffset with direction: rtl correctly');
Stephen McGruerce50d582019-03-01 03:00:02344
345test(function() {
346 const scrollerOverrides = new Map([['direction', 'rtl']]);
347 const scroller = setupScrollTimelineTest(scrollerOverrides);
348 // Set the timeRange such that currentTime maps directly to the value
349 // scrolled. The contents and scroller are square, so it suffices to compute
350 // one edge and use it for all the timelines.
351 const scrollerSize = scroller.scrollHeight - scroller.clientHeight;
352
353 // When the endScrollOffset is equal to the maximum scroll offset (and there
354 // are no fill modes), the endScrollOffset is treated as inclusive.
355 const inclusiveAutoScrollTimeline = new ScrollTimeline({
356 scrollSource: scroller,
357 timeRange: scrollerSize,
358 orientation: 'block',
359 endScrollOffset: 'auto'
360 });
361 const inclusiveLengthScrollTimeline = new ScrollTimeline({
362 scrollSource: scroller,
363 timeRange: scrollerSize,
364 orientation: 'block',
365 endScrollOffset: scrollerSize + 'px'
366 });
367 const inclusivePercentageScrollTimeline = new ScrollTimeline({
368 scrollSource: scroller,
369 timeRange: scrollerSize,
370 orientation: 'block',
371 endScrollOffset: '100%'
372 });
373 const inclusiveCalcScrollTimeline = new ScrollTimeline({
374 scrollSource: scroller,
375 timeRange: scrollerSize,
376 orientation: 'block',
377 endScrollOffset: 'calc(80% + ' + (0.2 * scrollerSize) + 'px)'
378 });
379
380 // With direction rtl offsets are inverted, such that scrollLeft ==
381 // scrollerSize is the 'zero' point for currentTime. However the
382 // endScrollOffset is an absolute distance along the offset, so doesn't need
383 // adjusting.
384
385 scroller.scrollLeft = 0;
386 let expectedCurrentTime = calculateCurrentTime(
387 scroller.scrollLeft, 0, scrollerSize, scrollerSize);
388
389 assert_equals(
390 inclusiveAutoScrollTimeline.currentTime, expectedCurrentTime,
391 'Inclusive auto timeline at the endScrollOffset point');
392 assert_equals(
393 inclusiveLengthScrollTimeline.currentTime, expectedCurrentTime,
394 'Inclusive length-based timeline at the endScrollOffset point');
395 assert_equals(
396 inclusivePercentageScrollTimeline.currentTime, expectedCurrentTime,
397 'Inclusive percentage-based timeline at the endScrollOffset point');
398 assert_equals(
399 inclusiveCalcScrollTimeline.currentTime, expectedCurrentTime,
400 'Inclusive calc-based timeline at the endScrollOffset point');
401}, 'currentTime handles endScrollOffset (inclusive case) with direction: rtl correctly');
Stephen McGruer26390b32018-12-10 15:47:18402</script>