Skip to content

Commit 2c60f0d

Browse files
committed
Improve syncscroll performance and accuracy with few UX tweaks
1 parent 20fbc99 commit 2c60f0d

2 files changed

Lines changed: 64 additions & 60 deletions

File tree

public/js/index.js

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,14 @@ $(window).error(function () {
713713
//setNeedRefresh();
714714
});
715715

716+
function autoSyncscroll() {
717+
if (editorHasFocus()) {
718+
syncScrollToView();
719+
} else {
720+
syncScrollToEdit();
721+
}
722+
}
723+
716724
var windowResizeDebounce = 200;
717725
var windowResize = _.debounce(windowResizeInner, windowResizeDebounce);
718726

@@ -727,11 +735,7 @@ function windowResizeInner(callback) {
727735
if (editor.getOption('scrollbarStyle') === 'native') {
728736
setTimeout(function () {
729737
clearMap();
730-
if (editorHasFocus()) {
731-
syncScrollToView();
732-
} else {
733-
syncScrollToEdit();
734-
}
738+
autoSyncscroll();
735739
updateScrollspy();
736740
if (callback && typeof callback === 'function')
737741
callback();
@@ -741,11 +745,7 @@ function windowResizeInner(callback) {
741745
editor.setOption('viewportMargin', Infinity);
742746
setTimeout(function () {
743747
clearMap();
744-
if (editorHasFocus()) {
745-
syncScrollToView();
746-
} else {
747-
syncScrollToEdit();
748-
}
748+
autoSyncscroll();
749749
editor.setOption('viewportMargin', viewportMargin);
750750
//add or update user cursors
751751
for (var i = 0; i < onlineUsers.length; i++) {
@@ -1029,12 +1029,12 @@ function changeMode(type) {
10291029

10301030
if (lastMode == modeType.view && currentMode == modeType.both) {
10311031
preventSyncScrollToView = 2;
1032-
syncScrollToEdit();
1032+
syncScrollToEdit(null, true);
10331033
}
10341034

10351035
if (lastMode == modeType.edit && currentMode == modeType.both) {
10361036
preventSyncScrollToEdit = 2;
1037-
syncScrollToView();
1037+
syncScrollToView(null, true);
10381038
}
10391039

10401040
if (lastMode == modeType.both && currentMode != modeType.both) {
@@ -2458,10 +2458,10 @@ editor.on('beforeChange', function (cm, change) {
24582458
cmClient.editorAdapter.ignoreNextChange = true;
24592459
});
24602460
editor.on('cut', function () {
2461-
windowResize(); //workaround for scrollMap
2461+
//na
24622462
});
24632463
editor.on('paste', function () {
2464-
windowResize(); //workaround for scrollMap
2464+
//na
24652465
});
24662466
editor.on('changes', function (cm, changes) {
24672467
updateHistory();
@@ -2630,11 +2630,7 @@ function updateViewInner() {
26302630
clearMap();
26312631
//buildMap();
26322632
updateTitleReminder();
2633-
if (editorHasFocus()) {
2634-
syncScrollToView();
2635-
} else {
2636-
syncScrollToEdit();
2637-
}
2633+
autoSyncscroll();
26382634
}
26392635

26402636
var updateHistoryDebounce = 600;

public/js/syncscroll.js

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ var syncscroll = true;
110110
var preventSyncScrollToEdit = false;
111111
var preventSyncScrollToView = false;
112112

113-
var editScrollThrottle = 2;
113+
var editScrollThrottle = 10;
114114
var viewScrollThrottle = 10;
115115
var buildMapThrottle = 100;
116116

@@ -214,7 +214,7 @@ function buildMapInner(callback) {
214214
// sync view scroll progress to edit
215215
var viewScrollingTimer = null;
216216

217-
function syncScrollToEdit(e) {
217+
function syncScrollToEdit(event, preventAnimate) {
218218
if (currentMode != modeType.both || !syncscroll) return;
219219
if (preventSyncScrollToEdit) {
220220
if (typeof preventSyncScrollToEdit === 'number') {
@@ -225,7 +225,9 @@ function syncScrollToEdit(e) {
225225
return;
226226
}
227227
if (!scrollMap || !lineHeightMap) {
228-
buildMap(syncScrollToEdit);
228+
buildMap(function () {
229+
syncScrollToEdit(event, preventAnimate);
230+
});
229231
return;
230232
}
231233
if (editScrolling) return;
@@ -263,24 +265,28 @@ function syncScrollToEdit(e) {
263265
posTo = preLastLineHeight;
264266
topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos);
265267
posToNextDiff = textHeight * topDiffPercent;
266-
posTo += Math.floor(posToNextDiff);
268+
posTo += Math.ceil(posToNextDiff);
267269
} else {
268270
posTo = lineNo * textHeight;
269271
topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo]);
270272
posToNextDiff = textHeight * lineDiff * topDiffPercent;
271-
posTo += Math.floor(posToNextDiff);
273+
posTo += Math.ceil(posToNextDiff);
272274
}
273275

274-
var posDiff = Math.abs(scrollInfo.top - posTo);
275-
var duration = posDiff / 50;
276-
duration = duration >= 100 ? duration : 100;
277-
ui.area.codemirrorScroll.stop(true, true).animate({
278-
scrollTop: posTo
279-
}, duration, "linear");
276+
if (preventAnimate) {
277+
ui.area.codemirrorScroll.scrollTop(posTo);
278+
} else {
279+
var posDiff = Math.abs(scrollInfo.top - posTo);
280+
var duration = posDiff / 50;
281+
duration = duration >= 100 ? duration : 100;
282+
ui.area.codemirrorScroll.stop(true, true).animate({
283+
scrollTop: posTo
284+
}, duration, "linear");
285+
}
280286

281287
viewScrolling = true;
282288
clearTimeout(viewScrollingTimer);
283-
viewScrollingTimer = setTimeout(viewScrollingTimeoutInner, duration * 1.2);
289+
viewScrollingTimer = setTimeout(viewScrollingTimeoutInner, duration * 1.5);
284290
}
285291

286292
function viewScrollingTimeoutInner() {
@@ -290,7 +296,7 @@ function viewScrollingTimeoutInner() {
290296
// sync edit scroll progress to view
291297
var editScrollingTimer = null;
292298

293-
function syncScrollToView(event, _lineNo) {
299+
function syncScrollToView(event, preventAnimate) {
294300
if (currentMode != modeType.both || !syncscroll) return;
295301
if (preventSyncScrollToView) {
296302
if (typeof preventSyncScrollToView === 'number') {
@@ -301,44 +307,46 @@ function syncScrollToView(event, _lineNo) {
301307
return;
302308
}
303309
if (!scrollMap || !lineHeightMap) {
304-
buildMap(syncScrollToView);
310+
buildMap(function () {
311+
syncScrollToView(event, preventAnimate);
312+
});
305313
return;
306314
}
307315
if (viewScrolling) return;
308316

309-
if (!_lineNo) {
310-
var lineNo, posTo;
311-
var topDiffPercent, posToNextDiff;
312-
var scrollInfo = editor.getScrollInfo();
313-
var textHeight = editor.defaultTextHeight();
314-
lineNo = Math.floor(scrollInfo.top / textHeight);
315-
// if reach the last line, will start lerp to the bottom
316-
var diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight);
317-
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
318-
topDiffPercent = diffToBottom / textHeight;
319-
posTo = scrollMap[lineNo + 1];
320-
posToNextDiff = (viewBottom - posTo) * topDiffPercent;
321-
posTo += Math.floor(posToNextDiff);
322-
} else {
323-
topDiffPercent = (scrollInfo.top % textHeight) / textHeight;
324-
posTo = scrollMap[lineNo];
325-
posToNextDiff = (scrollMap[lineNo + 1] - posTo) * topDiffPercent;
326-
posTo += Math.floor(posToNextDiff);
327-
}
317+
var lineNo, posTo;
318+
var topDiffPercent, posToNextDiff;
319+
var scrollInfo = editor.getScrollInfo();
320+
var textHeight = editor.defaultTextHeight();
321+
lineNo = Math.floor(scrollInfo.top / textHeight);
322+
// if reach the last line, will start lerp to the bottom
323+
var diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight);
324+
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
325+
topDiffPercent = diffToBottom / textHeight;
326+
posTo = scrollMap[lineNo + 1];
327+
posToNextDiff = (viewBottom - posTo) * topDiffPercent;
328+
posTo += Math.floor(posToNextDiff);
328329
} else {
329-
posTo = scrollMap[lineHeightMap[_lineNo]];
330+
topDiffPercent = (scrollInfo.top % textHeight) / textHeight;
331+
posTo = scrollMap[lineNo];
332+
posToNextDiff = (scrollMap[lineNo + 1] - posTo) * topDiffPercent;
333+
posTo += Math.floor(posToNextDiff);
330334
}
331335

332-
var posDiff = Math.abs(ui.area.view.scrollTop() - posTo);
333-
var duration = posDiff / 50;
334-
duration = duration >= 100 ? duration : 100;
335-
ui.area.view.stop(true, true).animate({
336-
scrollTop: posTo
337-
}, duration, "linear");
336+
if (preventAnimate) {
337+
ui.area.view.scrollTop(posTo);
338+
} else {
339+
var posDiff = Math.abs(ui.area.view.scrollTop() - posTo);
340+
var duration = posDiff / 50;
341+
duration = duration >= 100 ? duration : 100;
342+
ui.area.view.stop(true, true).animate({
343+
scrollTop: posTo
344+
}, duration, "linear");
345+
}
338346

339347
editScrolling = true;
340348
clearTimeout(editScrollingTimer);
341-
editScrollingTimer = setTimeout(editScrollingTimeoutInner, duration * 1.2);
349+
editScrollingTimer = setTimeout(editScrollingTimeoutInner, duration * 1.5);
342350
}
343351

344352
function editScrollingTimeoutInner() {

0 commit comments

Comments
 (0)