8
8
< script src ="testcommon.js "> </ script >
9
9
< style >
10
10
.scroller {
11
- overflow : auto ;
12
- height : 100 px ;
13
- width : 100 px ;
11
+ overflow : hidden ;
12
+ height : 200 px ;
13
+ width : 200 px ;
14
14
}
15
15
.contents {
16
- height : 1000px ;
16
+ /* Make scroll range 1000 to simplify the math and avoid rounding errors */
17
+ height : 1200px ;
17
18
width : 100% ;
18
19
}
19
20
</ style >
57
58
*/
58
59
const test_cases = [
59
60
// Case 1: No delays. Effect starts at the same time as the timeline.
60
- [ [ "before timeline start" , 0 , 0 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
61
- [ [ "at timeline start" , 0 , 0 , 0.2 ] , [ 0 , 0 , 0 , 0 , "active" ] ] ,
62
- [ [ "in timeline range" , 0 , 0 , 0.5 ] , [ 50 , 50 , 50 , 0.5 , "active" ] ] ,
63
- [ [ "at timeline end" , 0 , 0 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
64
- [ [ "after timeline end" , 0 , 0 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
61
+ [ [ "before timeline start" , 0 , 0 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
62
+ [ [ "at timeline start" , 0 , 0 , 0.25 ] , [ 0 , 0 , 0 , 0 , "active" ] ] ,
63
+ [ [ "in timeline range" , 0 , 0 , 0.50 ] , [ 50 , 50 , 50 , 0.5 , "active" ] ] ,
64
+ [ [ "at timeline end" , 0 , 0 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
65
+ [ [ "after timeline end" , 0 , 0 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
65
66
66
67
// Case 2: Positive delay, no endDelay.
67
- [ [ "before timeline start" , 500 , 0 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
68
- [ [ "at timeline start" , 500 , 0 , 0.2 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
69
- [ [ "before effect delay" , 500 , 0 , 0.4 ] , [ 33.333 , 33.333 , 33.333 , null , "before" ] ] ,
70
- [ [ "at effect start" , 500 , 0 , 0.5 ] , [ 50 , 50 , 50 , 0 , "active" ] ] ,
71
- [ [ "in timeline range" , 500 , 0 , 0.65 ] , [ 75 , 75 , 75 , 0.5 , "active" ] ] ,
72
- [ [ "at timeline end" , 500 , 0 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
73
- [ [ "after timeline end" , 500 , 0 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
68
+ // effect start = 100% * start / (start + duration + end)
69
+ // = 100% * 500 / (500 + 500 + 0) = 50%
70
+ [ [ "before timeline start" , 500 , 0 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
71
+ [ [ "at timeline start" , 500 , 0 , 0.25 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
72
+ [ [ "before effect delay" , 500 , 0 , 0.30 ] , [ 10 , 10 , 10 , null , "before" ] ] ,
73
+ [ [ "at effect start" , 500 , 0 , 0.50 ] , [ 50 , 50 , 50 , 0 , "active" ] ] ,
74
+ [ [ "in timeline range" , 500 , 0 , 0.65 ] , [ 80 , 80 , 80 , 0.6 , "active" ] ] ,
75
+ [ [ "at timeline end" , 500 , 0 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
76
+ [ [ "after timeline end" , 500 , 0 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
74
77
75
78
// Case 3: Negative delay, no endDelay.
76
- [ [ "before timeline start" , - 250 , 0 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
77
- [ [ "at timeline start" , - 250 , 0 , 0.2 ] , [ 0 , 0 , 0 , 0.5 , "active" ] ] ,
78
- [ [ "in timeline range" , - 250 , 0 , 0.5 ] , [ 50 , 50 , 50 , 0.75 , "active" ] ] ,
79
- [ [ "at timeline end" , - 250 , 0 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
80
- [ [ "after timeline end" , - 250 , 0 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
79
+ [ [ "before timeline start" , - 250 , 0 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
80
+ [ [ "at timeline start" , - 250 , 0 , 0.25 ] , [ 0 , 0 , 0 , 0.5 , "active" ] ] ,
81
+ [ [ "in timeline range" , - 250 , 0 , 0.50 ] , [ 50 , 50 , 50 , 0.75 , "active" ] ] ,
82
+ [ [ "at timeline end" , - 250 , 0 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
83
+ [ [ "after timeline end" , - 250 , 0 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
81
84
82
85
// Case 4: No delay, negative endDelay. Effect will never progress to 100%
83
- [ [ "before timeline start" , 0 , - 250 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
84
- [ [ "at timeline start" , 0 , - 250 , 0.2 ] , [ 0 , 0 , 0 , 0 , "active" ] ] ,
85
- [ [ "in timeline range" , 0 , - 250 , 0.799 ] , [ 99.833 , 99.833 , 99.833 , 0.499 , "active" ] ] ,
86
- [ [ "at timeline end" , 0 , - 250 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
87
- [ [ "after timeline end" , 0 , - 250 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
86
+ [ [ "before timeline start" , 0 , - 250 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
87
+ [ [ "at timeline start" , 0 , - 250 , 0.25 ] , [ 0 , 0 , 0 , 0 , "active" ] ] ,
88
+ [ [ "in timeline range" , 0 , - 250 , 0.50 ] , [ 50 , 50 , 50 , 0.25 , "active" ] ] ,
89
+ [ [ "at timeline end" , 0 , - 250 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
90
+ [ [ "after timeline end" , 0 , - 250 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
88
91
89
92
// Case 5: No delay, positive endDelay.
90
- [ [ "before timeline start" , 0 , 500 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
91
- [ [ "at timeline start" , 0 , 500 , 0.2 ] , [ 0 , 0 , 0 , 0 , "active" ] ] ,
92
- [ [ "in timeline range" , 0 , 500 , 0.4 ] , [ 33.333 , 33.333 , 33.333 , 0.666 , "active" ] ] ,
93
- [ [ "at effect end" , 0 , 500 , 0.5 ] , [ 50 , 50 , 50 , null , "after" ] ] ,
94
- [ [ "after effect endDelay" , 0 , 500 , 0.6 ] , [ 66.666 , 66.666 , 66.666 , null , "after" ] ] ,
95
- [ [ "at timeline end" , 0 , 500 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
96
- [ [ "after timeline end" , 0 , 500 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
93
+ // effect end = 100% * (start + duration) / (start + duration + end)
94
+ // = 100% * (0 + 500) / (0 + 500 + 500) = 50%
95
+ [ [ "before timeline start" , 0 , 500 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
96
+ [ [ "at timeline start" , 0 , 500 , 0.25 ] , [ 0 , 0 , 0 , 0 , "active" ] ] ,
97
+ [ [ "in timeline range" , 0 , 500 , 0.40 ] , [ 30 , 30 , 30 , 0.6 , "active" ] ] ,
98
+ [ [ "at effect end" , 0 , 500 , 0.50 ] , [ 50 , 50 , 50 , null , "after" ] ] ,
99
+ [ [ "after effect endDelay" , 0 , 500 , 0.60 ] , [ 70 , 70 , 70 , null , "after" ] ] ,
100
+ [ [ "at timeline end" , 0 , 500 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
101
+ [ [ "after timeline end" , 0 , 500 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
97
102
98
103
// Case 6: Positive delay, positive endDelay.
99
- [ [ "before timeline start" , 500 , 500 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
100
- [ [ "at timeline start" , 500 , 500 , 0.2 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
101
- [ [ "before effect delay" , 500 , 500 , 0.3 ] , [ 16.666 , 16.666 , 16.666 , null , "before" ] ] ,
102
- [ [ "at effect start" , 500 , 500 , 0.400001 ] , [ 33.333 , 33.333 , 33.333 , 0 , "active" ] ] ,
103
- [ [ "in timeline range" , 500 , 500 , 0.5 ] , [ 50 , 50 , 50 , 0.5 , "active" ] ] ,
104
- [ [ "at effect end" , 500 , 500 , 0.600001 ] , [ 66.666 , 66.666 , 66.666 , null , "after" ] ] ,
105
- [ [ "after effect endDelay" , 500 , 500 , 0.7 ] , [ 83.333 , 83.333 , 83.333 , null , "after" ] ] ,
106
- [ [ "at timeline end" , 500 , 500 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
107
- [ [ "after timeline end" , 500 , 500 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
104
+ // Delays chosen to make timeline an integer percentage at the effect start
105
+ // and end boundaries.
106
+ // effect start = 100% * start / (start + duration + end)
107
+ // = 100% * 375 / (375 + 500 + 375) = 30%
108
+ // effect end = 100% * (start + duration) / (start + duration + end)
109
+ // = 100% * (375 + 500) / (375 + 500 + 375) = 70%
110
+ [ [ "before timeline start" , 375 , 375 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
111
+ [ [ "at timeline start" , 375 , 375 , 0.25 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
112
+ [ [ "before effect delay" , 375 , 375 , 0.27 ] , [ 4 , 4 , 4 , null , "before" ] ] ,
113
+ [ [ "at effect start" , 375 , 375 , 0.40 ] , [ 30 , 30 , 30 , 0 , "active" ] ] ,
114
+ [ [ "in timeline range" , 375 , 375 , 0.50 ] , [ 50 , 50 , 50 , 0.5 , "active" ] ] ,
115
+ [ [ "at effect end" , 375 , 375 , 0.60 ] , [ 70 , 70 , 70 , null , "after" ] ] ,
116
+ [ [ "after effect endDelay" , 375 , 375 , 0.70 ] , [ 90 , 90 , 90 , null , "after" ] ] ,
117
+ [ [ "at timeline end" , 375 , 375 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
118
+ [ [ "after timeline end" , 375 , 375 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
108
119
109
120
// Case 7: Positive delay, negative endDelay.
110
- [ [ "before timeline start" , 500 , - 250 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
111
- [ [ "at timeline start" , 500 , - 250 , 0.2 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
112
- [ [ "before effect delay" , 500 , - 250 , 0.4 ] , [ 33.333 , 33.333 , 33.333 , null , "before" ] ] ,
113
- [ [ "at effect start" , 500 , - 250 , 0.600001 ] , [ 66.666 , 66.666 , 66.666 , 0 , "active" ] ] ,
114
- [ [ "in timeline range" , 500 , - 250 , 0.799 ] , [ 99.833 , 99.833 , 99.833 , 0.497 , "active" ] ] ,
115
- [ [ "at timeline end" , 500 , - 250 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
116
- [ [ "after timeline end" , 500 , - 250 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
121
+ // effect start = 100% * start / (start + duration + end)
122
+ // = 100% * 600 / (600 + 500 - 100) = 60%
123
+ [ [ "before timeline start" , 600 , - 100 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
124
+ [ [ "at timeline start" , 600 , - 100 , 0.25 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
125
+ [ [ "before effect delay" , 600 , - 100 , 0.40 ] , [ 30 , 30 , 30 , null , "before" ] ] ,
126
+ [ [ "at effect start" , 600 , - 100 , 0.55 ] , [ 60 , 60 , 60 , 0 , "active" ] ] ,
127
+ [ [ "in timeline range" , 600 , - 100 , 0.70 ] , [ 90 , 90 , 90 , 0.6 , "active" ] ] ,
128
+ [ [ "at timeline end" , 600 , - 100 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
129
+ [ [ "after timeline end" , 600 , - 100 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
117
130
118
131
// Case 8: Negative delay, positive endDelay.
119
- [ [ "before timeline start" , - 250 , 500 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
120
- [ [ "at timeline start" , - 250 , 500 , 0.2 ] , [ 0 , 0 , 0 , 0.5 , "active" ] ] ,
121
- [ [ "in timeline range" , - 250 , 500 , 0.3 ] , [ 16.666 , 16.666 , 16.666 , 0.75 , "active" ] ] ,
122
- [ [ "at effect end" , - 250 , 500 , 0.400001 ] , [ 33.333 , 33.333 , 33.333 , null , "after" ] ] ,
123
- [ [ "after effect endDelay" , - 250 , 500 , 0.7 ] , [ 83.333 , 83.333 , 83.333 , null , "after" ] ] ,
124
- [ [ "at timeline end" , - 250 , 500 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
125
- [ [ "after timeline end" , - 250 , 500 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
132
+ // effect end = 100% * (start + duration) / (start + duration + end)
133
+ // = (-100 + 500) / (-100 + 500 + 600) = 40%
134
+ [ [ "before timeline start" , - 100 , 600 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
135
+ [ [ "at timeline start" , - 100 , 600 , 0.25 ] , [ 0 , 0 , 0 , 0.2 , "active" ] ] ,
136
+ [ [ "in timeline range" , - 100 , 600 , 0.30 ] , [ 10 , 10 , 10 , 0.4 , "active" ] ] ,
137
+ [ [ "at effect end" , - 100 , 600 , 0.45 ] , [ 40 , 40 , 40 , null , "after" ] ] ,
138
+ [ [ "after effect endDelay" , - 100 , 600 , 0.70 ] , [ 90 , 90 , 90 , null , "after" ] ] ,
139
+ [ [ "at timeline end" , - 100 , 600 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
140
+ [ [ "after timeline end" , - 100 , 600 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
126
141
127
142
// Case 9: Negative delay, negative endDelay.
128
- [ [ "before timeline start" , - 200 , - 200 , 0.1 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
129
- [ [ "at timeline start" , - 200 , - 200 , 0.2 ] , [ 0 , 0 , 0 , 0.4 , "active" ] ] ,
130
- [ [ "in timeline range" , - 200 , - 200 , 0.799 ] , [ 99.833 , 99.833 , 99.833 , 0.6 , "active" ] ] ,
131
- [ [ "at timeline end" , - 200 , - 200 , 0.8 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
132
- [ [ "after timeline end" , - 200 , - 200 , 0.9 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
143
+ [ [ "before timeline start" , - 200 , - 200 , 0.10 ] , [ 0 , 0 , 0 , null , "before" ] ] ,
144
+ [ [ "at timeline start" , - 200 , - 200 , 0.25 ] , [ 0 , 0 , 0 , 0.4 , "active" ] ] ,
145
+ [ [ "in timeline range" , - 200 , - 200 , 0.50 ] , [ 50 , 50 , 50 , 0.5 , "active" ] ] ,
146
+ [ [ "at timeline end" , - 200 , - 200 , 0.75 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
147
+ [ [ "after timeline end" , - 200 , - 200 , 0.90 ] , [ 100 , 100 , 100 , null , "after" ] ] ,
133
148
] ;
134
149
135
150
for ( const test_case of test_cases ) {
149
164
delay , end_delay , scroll_percentage , expected ) {
150
165
return async t => {
151
166
const target = createDiv ( t ) ;
167
+ // timetime time is:
168
+ // 100% * (scroll - start)/(end - start) if (start <= scroll <= end).
169
+ // Choose convenient offsets to avoid fractional percentages with timeline
170
+ // time. Choosing the offset range [25%, 75%] results in:
171
+ // timeline time = 2 * (scroll% - start%) when 25% < scroll% < 75%.
152
172
const timeline =
153
- createScrollTimelineWithOffsets ( t , CSS . percent ( 20 ) , CSS . percent ( 80 ) ) ;
173
+ createScrollTimelineWithOffsets ( t , CSS . percent ( 25 ) , CSS . percent ( 75 ) ) ;
154
174
const effect = new KeyframeEffect (
155
175
target ,
156
176
{
378
398
} , 'Animation effect is still applied after pausing and making timeline ' +
379
399
'inactive.' ) ;
380
400
381
- </ script >
401
+ </ script >
0 commit comments