Skip to content
This repository was archived by the owner on Jun 15, 2022. It is now read-only.

Commit f35d8c1

Browse files
authored
Merge pull request #20 from dagjaneiro/optimize-synced-scroll
feat: optimize synced scroll
2 parents 8795cc2 + a90de8e commit f35d8c1

File tree

1 file changed

+46
-13
lines changed

1 file changed

+46
-13
lines changed

app/components/Home.js

+46-13
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,29 @@ export default class Home extends React.Component {
2929
this.connectToBridge();
3030
this.updatePreviewText();
3131
this.addChangeListener();
32-
this.addScrollListeners();
3332

3433
this.configureResizer();
3534
this.addTabHandler();
35+
36+
this.scrollTriggers = {};
37+
this.scrollHandlers = [
38+
{el: this.editor, handler: this.scrollHandler(this.editor, this.preview)},
39+
{el: this.preview, handlerthis.scrollHandler(this.preview, this.editor)}
40+
];
41+
}
42+
43+
componentWillUpdate(nextProps, nextState) {
44+
var prevMode = this.state.mode.mode;
45+
var nextMode = nextState.mode.mode;
46+
47+
// If we changed to Split mode we add the scroll listeners
48+
if(prevMode !== nextMode) {
49+
if(nextMode === SplitMode) {
50+
this.addScrollListeners();
51+
} else {
52+
this.removeScrollListeners();
53+
}
54+
}
3655
}
3756

3857
setModeFromModeValue(value) {
@@ -149,26 +168,40 @@ export default class Home extends React.Component {
149168
}
150169

151170
addScrollListeners() {
152-
this.scrollTriggers = {};
153-
this.syncScroll(this.editor, this.preview);
154-
this.syncScroll(this.preview, this.editor);
171+
this.scrollHandlers.forEach(({el, handler}) => el.addEventListener('scroll', handler));
155172
}
156173

157-
syncScroll(source, destination) {
158-
source.addEventListener('scroll', (event) => {
174+
removeScrollListeners() {
175+
this.scrollHandlers.forEach(({el, handler}) => el.removeEventListener('scroll', handler));
176+
}
177+
178+
scrollHandler = (source, destination) => {
179+
var frameRequested;
180+
181+
return (event) => {
159182
// Avoid the cascading effect by not handling the event if it was triggered initially by this element
160-
if (this.scrollTriggers[source] === true) {
183+
if(this.scrollTriggers[source] === true) {
161184
this.scrollTriggers[source] = false;
162185
return;
163186
}
164187
this.scrollTriggers[source] = true;
165188

166-
var target = event.target
167-
var height = target.scrollHeight - target.clientHeight;
168-
var ratio = parseFloat(target.scrollTop) / height;
169-
var move = (destination.scrollHeight - destination.clientHeight) * ratio;
170-
destination.scrollTop = move;
171-
})
189+
// Only request the animation frame once until it gets processed
190+
if(frameRequested) {
191+
return;
192+
}
193+
frameRequested = true;
194+
195+
window.requestAnimationFrame(() => {
196+
var target = event.target
197+
var height = target.scrollHeight - target.clientHeight;
198+
var ratio = parseFloat(target.scrollTop) / height;
199+
var move = (destination.scrollHeight - destination.clientHeight) * ratio;
200+
destination.scrollTop = move;
201+
202+
frameRequested = false;
203+
});
204+
}
172205
}
173206

174207
removeSelection() {

0 commit comments

Comments
 (0)