EN
JavaScript - check for scrollTo() method got finished
10 points
In this article, we would like to show how to detect when scrollTo() method finished execution in JavaScript.
There is not available event that signals when scrollTo()
method ends execution, so there is needed to use some trick to solve the problem. In the example solution we provide reusable logic that checks state once per some time.
Example solution:
xxxxxxxxxx
1
function SmoothScroller(element, interval = 100, chances = 3, tolerance = 1.0) {
2
const bound = tolerance * tolerance;
3
let id = null;
4
this.scroll = (x, y, callback) => {
5
if (id) {
6
clearTimeout(id);
7
id = null;
8
}
9
const options = {
10
left: x,
11
top: y,
12
behavior: 'smooth'
13
};
14
element.scrollTo(options);
15
if (callback) {
16
let state = +Infinity;
17
const action = () => {
18
const elementX = element.scrollLeft;
19
const elementY = element.scrollTop;
20
const dx = x - elementX;
21
const dy = y - elementY;
22
const square = dx * dx + dy * dy;
23
if (square < bound) {
24
callback('done');
25
} else {
26
if (square === state) {
27
if (chances > 0) {
28
state = square;
29
chances -= 1;
30
id = setTimeout(action, interval);
31
} else {
32
callback('canceled');
33
}
34
} else {
35
state = square;
36
id = setTimeout(action, interval);
37
}
38
}
39
};
40
id = setTimeout(action, interval);
41
}
42
};
43
this.stop = () => {
44
if (id) {
45
clearTimeout(id);
46
id = null;
47
}
48
};
49
}
50
51
52
// Usage example:
53
54
const element = // e.g. document.querySelector('#element');
55
const scroller = new SmoothScroller(element);
56
57
scroller.scroll(50, 100, (status) => console.log(`status: ${status}`)); // scrolls into (x, y) = (50, 100) position
Where:
- in
SmoothScroller
class constructor:
element
represents handle to HTML element that is scrolled,interval
means how often state checking is done, e.g.100
means once per 100ms,chances
means how many state failing checks are accepted, e.g. when something or someone tries to stop scrolling ro changes scrolling destination point,tolerance
was introduced to makes possible floating-point values usage by web browser when window has sets zoom,- in
scroll()
method:
x
andy
means scrolling destination point,callback
means function called when scrolling is done or canceled.
xxxxxxxxxx
1
<style>
2
3
div.element {
4
border: 1px solid silver;
5
width: 400px;
6
height: 300px;
7
white-space: nowrap;
8
overflow: auto;
9
}
10
11
</style>
12
<script>
13
14
// Common reusable logic:
15
16
function SmoothScroller(element, interval = 100, chances = 3, tolerance = 1.0) {
17
const bound = tolerance * tolerance;
18
let id = null;
19
this.scroll = (x, y, callback) => {
20
if (id) {
21
clearTimeout(id);
22
id = null;
23
}
24
const options = {
25
left: x,
26
top: y,
27
behavior: 'smooth'
28
};
29
element.scrollTo(options);
30
if (callback) {
31
let state = +Infinity;
32
const action = () => {
33
const elementX = element.scrollLeft;
34
const elementY = element.scrollTop;
35
const dx = x - elementX;
36
const dy = y - elementY;
37
const square = dx * dx + dy * dy;
38
if (square < bound) {
39
callback('done');
40
} else {
41
if (square === state) {
42
if (chances > 0) {
43
state = square;
44
chances -= 1;
45
id = setTimeout(action, interval);
46
} else {
47
callback('canceled');
48
}
49
} else {
50
state = square;
51
id = setTimeout(action, interval);
52
}
53
}
54
};
55
id = setTimeout(action, interval);
56
}
57
};
58
this.stop = () => {
59
if (id) {
60
clearTimeout(id);
61
id = null;
62
}
63
};
64
}
65
66
</script>
67
<button onclick="scrollElement(0, 0)">Scroll to (0, 0)</button>
68
<button onclick="scrollElement(400, 500)">Scroll to (400, 500)</button>
69
<button onclick="scrollElement(0, 1000)">Scroll to (0, 1000)</button>
70
<br /><br />
71
<div class="element" id="element">
72
<!-- Automatically generated text is placed here ... -->
73
</div>
74
<script>
75
76
const handle = document.querySelector('#element');
77
78
// Element content preparation:
79
80
let text = '';
81
for (let i = 0; i < 100; ++i) {
82
for (let j = 0; j < 10; ++j) {
83
text += 'Verry long line ...';
84
}
85
text += '\n';
86
}
87
handle.innerText = text;
88
89
// Element scroller usage:
90
91
const scroller = new SmoothScroller(handle);
92
function scrollElement(x, y) {
93
const callback = (status) => {
94
console.log(`status: ${status}`);
95
};
96
scroller.scroll(x, y, callback);
97
}
98
99
</script>