From e9b0ce8e04552f6839cd5e353343a6d984d5027e Mon Sep 17 00:00:00 2001 From: "Cheng-Han, Wu" Date: Fri, 27 May 2016 00:12:07 +0800 Subject: [PATCH] Update to improve sync scroll to edit performance and fix sync scroll behavior on many situations --- public/js/index.js | 41 ++++++++++++++++++++++----- public/js/syncscroll.js | 62 ++++++++++++++++++++++++----------------- 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/public/js/index.js b/public/js/index.js index 29e2297..832e0d1 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -722,8 +722,11 @@ function windowResizeInner(callback) { if (loaded) { if (editor.getOption('scrollbarStyle') === 'native') { clearMap(); - syncScrollToView(); - syncScrollToEdit(); + if (editorHasFocus()) { + syncScrollToView(); + } else { + syncScrollToEdit(); + } updateScrollspy(); if (callback && typeof callback === 'function') callback(); @@ -732,8 +735,11 @@ function windowResizeInner(callback) { editor.setOption('viewportMargin', Infinity); setTimeout(function () { clearMap(); - syncScrollToView(); - syncScrollToEdit(); + if (editorHasFocus()) { + syncScrollToView(); + } else { + syncScrollToEdit(); + } editor.setOption('viewportMargin', viewportMargin); //add or update user cursors for (var i = 0; i < onlineUsers.length; i++) { @@ -774,6 +780,7 @@ function checkResponsive() { } var lastEditorWidth = 0; +var previousFocusOnEditor = null; function checkEditorStyle() { var desireHeight = statusBar ? (ui.area.edit.height() - statusBar.outerHeight()) : ui.area.edit.height(); @@ -806,6 +813,11 @@ function checkEditorStyle() { } if (!ui.area.resize.syncToggle.length) { ui.area.resize.syncToggle = $(''); + ui.area.resize.syncToggle.hover(function () { + previousFocusOnEditor = editorHasFocus(); + }, function () { + previousFocusOnEditor = null; + }); ui.area.resize.syncToggle.click(function () { syncscroll = !syncscroll; checkSyncToggle(); @@ -822,6 +834,13 @@ function checkEditorStyle() { function checkSyncToggle() { if (syncscroll) { + if (previousFocusOnEditor) { + preventSyncScrollToView = false; + syncScrollToView(); + } else { + preventSyncScrollToEdit = false; + syncScrollToEdit(); + } ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link'); } else { ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink'); @@ -1003,9 +1022,14 @@ function changeMode(type) { restoreInfo(); if (lastMode == modeType.view && currentMode == modeType.both) { - preventSyncScrollToView = true; + preventSyncScrollToView = 2; syncScrollToEdit(); } + + if (lastMode == modeType.edit && currentMode == modeType.both) { + preventSyncScrollToEdit = 2; + syncScrollToView(); + } if (lastMode != modeType.edit && currentMode == modeType.edit) { editor.refresh(); @@ -2595,8 +2619,11 @@ function updateViewInner() { clearMap(); //buildMap(); updateTitleReminder(); - syncScrollToView(); - syncScrollToEdit(); + if (editorHasFocus()) { + syncScrollToView(); + } else { + syncScrollToEdit(); + } } var updateHistoryDebounce = 600; diff --git a/public/js/syncscroll.js b/public/js/syncscroll.js index 348af2d..9d0bbe0 100644 --- a/public/js/syncscroll.js +++ b/public/js/syncscroll.js @@ -110,17 +110,15 @@ var syncscroll = true; var preventSyncScrollToEdit = false; var preventSyncScrollToView = false; -var editScrollThrottle = 1; +var editScrollThrottle = 2; var viewScrollThrottle = 10; var buildMapThrottle = 100; var viewScrolling = false; -var viewScrollingDelay = 200; -var viewScrollingTimer = null; +var viewScrollingDebounce = 200; var editScrolling = false; -var editScrollingDelay = 100; -var editScrollingTimer = null; +var editScrollingDebounce = 200; if (editor.getOption('scrollbarStyle') === 'native') { ui.area.codemirrorScroll.on('scroll', _.throttle(syncScrollToView, editScrollThrottle)); @@ -145,7 +143,7 @@ var buildMap = _.throttle(buildMapInner, buildMapThrottle); // Build offsets for each line (lines can be wrapped) // That's a bit dirty to process each line everytime, but ok for demo. // Optimizations are required only for big texts. -function buildMapInner(syncBack) { +function buildMapInner(callback) { var i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount, acc, _scrollMap; @@ -217,12 +215,15 @@ function buildMapInner(syncBack) { scrollMap = _scrollMap; lineHeightMap = _lineHeightMap; - if (loaded && syncBack) { - syncScrollToView(); - syncScrollToEdit(); - } + if (loaded && callback) callback(); } +// sync view scroll progress to edit +var viewScrollingTimeout = _.debounce(viewScrollingTimeoutInner, viewScrollingDebounce); + +function viewScrollingTimeoutInner() { + viewScrolling = false; +} function syncScrollToEdit(e) { if (currentMode != modeType.both || !syncscroll) return; @@ -235,7 +236,7 @@ function syncScrollToEdit(e) { return; } if (!scrollMap || !lineHeightMap) { - buildMap(true); + buildMap(syncScrollToEdit); return; } if (editScrolling) return; @@ -272,21 +273,30 @@ function syncScrollToEdit(e) { if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) { posTo = preLastLineHeight; topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos); - posToNextDiff = Math.ceil(textHeight * topDiffPercent); + posToNextDiff = textHeight * topDiffPercent; + posTo += Math.floor(posToNextDiff); } else { posTo = lineNo * textHeight; topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo]); - posToNextDiff = Math.ceil(textHeight * lineDiff * topDiffPercent); + posToNextDiff = textHeight * lineDiff * topDiffPercent; + posTo += Math.floor(posToNextDiff); } - editor.scrollTo(0, posTo + posToNextDiff); - preventSyncScrollToView = true; + var posDiff = Math.abs(scrollInfo.top - posTo); + var duration = posDiff / 50; + ui.area.codemirrorScroll.stop(true, true).animate({ + scrollTop: posTo + }, duration >= 100 ? duration : 100, "linear"); viewScrolling = true; - clearTimeout(viewScrollingTimer); - viewScrollingTimer = setTimeout(function () { - viewScrolling = false; - }, viewScrollingDelay); + viewScrollingTimeout(); +} + +// sync edit scroll progress to view +var editScrollingTimeout = _.debounce(editScrollingTimeoutInner, editScrollingDebounce); + +function editScrollingTimeoutInner() { + editScrolling = false; } function syncScrollToView(event, _lineNo) { @@ -300,7 +310,7 @@ function syncScrollToView(event, _lineNo) { return; } if (!scrollMap || !lineHeightMap) { - buildMap(true); + buildMap(syncScrollToView); return; } if (viewScrolling) return; @@ -328,12 +338,12 @@ function syncScrollToView(event, _lineNo) { posTo = scrollMap[lineHeightMap[_lineNo]]; } - ui.area.view.stop(true, true).scrollTop(posTo); - preventSyncScrollToEdit = true; + var posDiff = Math.abs(ui.area.view.scrollTop() - posTo); + var duration = posDiff / 50; + ui.area.view.stop(true, true).animate({ + scrollTop: posTo + }, duration >= 100 ? duration : 100, "linear"); editScrolling = true; - clearTimeout(editScrollingTimer); - editScrollingTimer = setTimeout(function () { - editScrolling = false; - }, editScrollingDelay); + editScrollingTimeout(); } \ No newline at end of file