Add support of sync scrolling to edit area

This commit is contained in:
Cheng-Han, Wu 2016-05-25 13:25:05 +08:00
parent f3418a619c
commit bf1dc237a9
2 changed files with 81 additions and 35 deletions

View file

@ -743,6 +743,7 @@ function windowResizeInner(callback) {
if (editor.getOption('scrollbarStyle') === 'native') { if (editor.getOption('scrollbarStyle') === 'native') {
clearMap(); clearMap();
syncScrollToView(); syncScrollToView();
syncScrollToEdit();
updateScrollspy(); updateScrollspy();
if (callback && typeof callback === 'function') if (callback && typeof callback === 'function')
callback(); callback();
@ -752,6 +753,7 @@ function windowResizeInner(callback) {
setTimeout(function () { setTimeout(function () {
clearMap(); clearMap();
syncScrollToView(); syncScrollToView();
syncScrollToEdit();
editor.setOption('viewportMargin', viewportMargin); editor.setOption('viewportMargin', viewportMargin);
//add or update user cursors //add or update user cursors
for (var i = 0; i < onlineUsers.length; i++) { for (var i = 0; i < onlineUsers.length; i++) {
@ -822,7 +824,6 @@ function checkEditorScrollbar() {
// workaround simple scroll bar knob // workaround simple scroll bar knob
// will get wrong position when editor height changed // will get wrong position when editor height changed
var scrollInfo = editor.getScrollInfo(); var scrollInfo = editor.getScrollInfo();
if (!preventSyncScroll) preventSyncScroll = true;
editor.scrollTo(null, scrollInfo.top - 1); editor.scrollTo(null, scrollInfo.top - 1);
editor.scrollTo(null, scrollInfo.top); editor.scrollTo(null, scrollInfo.top);
} }
@ -1027,15 +1028,6 @@ var unlockNavbar = _.debounce(function () {
$('.navbar').removeClass('locked'); $('.navbar').removeClass('locked');
}, 200); }, 200);
function syncScrollToEdit() {
if (!scrollMap || !lineHeightMap)
buildMapInner();
var scrollMapNearest = closestIndex(scrollMap, lastInfo.view.scroll.top);
var lineHeightMapNearest = closestIndex(lineHeightMap, scrollMapNearest);
var height = lineHeightMapNearest * defaultTextHeight;
editor.scrollTo(null, height);
}
function closestIndex(arr, closestTo) { function closestIndex(arr, closestTo) {
var closest = Math.max.apply(null, arr); //Get the highest number in arr in case it match nothing. var closest = Math.max.apply(null, arr); //Get the highest number in arr in case it match nothing.
var index = 0; var index = 0;
@ -2422,11 +2414,9 @@ editor.on('beforeChange', function (cm, change) {
cmClient.editorAdapter.ignoreNextChange = true; cmClient.editorAdapter.ignoreNextChange = true;
}); });
editor.on('cut', function () { editor.on('cut', function () {
preventSyncScroll = 3;
windowResize(); //workaround for scrollMap windowResize(); //workaround for scrollMap
}); });
editor.on('paste', function () { editor.on('paste', function () {
preventSyncScroll = 3;
windowResize(); //workaround for scrollMap windowResize(); //workaround for scrollMap
}); });
editor.on('changes', function (cm, changes) { editor.on('changes', function (cm, changes) {
@ -2596,6 +2586,8 @@ function updateViewInner() {
clearMap(); clearMap();
//buildMap(); //buildMap();
updateTitleReminder(); updateTitleReminder();
syncScrollToView();
syncScrollToEdit();
} }
var updateHistoryDebounce = 600; var updateHistoryDebounce = 600;

View file

@ -107,28 +107,89 @@ md.use(window.markdownitContainer, 'danger', { render: renderContainer });
var preventSyncScroll = false; var preventSyncScroll = false;
//var editorScrollThrottle = 100; var editScrollThrottle = 1;
var viewScrollThrottle = 20;
var buildMapThrottle = 100; var buildMapThrottle = 100;
var viewScrolling = false; var viewScrolling = false;
var viewScrollingDelay = 200; var viewScrollingDelay = 200;
var viewScrollingTimer = null; var viewScrollingTimer = null;
//editor.on('scroll', _.throttle(syncScrollToView, editorScrollThrottle)); var editScrolling = false;
var editScrollingDelay = 100;
var editScrollingTimer = null;
if (editor.getOption('scrollbarStyle') === 'native') { if (editor.getOption('scrollbarStyle') === 'native') {
ui.area.codemirrorScroll.on('scroll', syncScrollToView); ui.area.codemirrorScroll.on('scroll', _.throttle(syncScrollToView, editScrollThrottle));
} else { } else {
editor.on('scroll', syncScrollToView); editor.on('scroll', _.throttle(syncScrollToView, editScrollThrottle));
} }
ui.area.view.on('scroll', function () { ui.area.view.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle));
var preventViewScroll = false;
function syncScrollToEdit(e) {
if (currentMode != modeType.both) return;
if (preventViewScroll) {
if (typeof preventViewScroll === 'number') {
preventViewScroll--;
} else {
preventViewScroll = false;
}
return;
}
if (!scrollMap || !lineHeightMap) {
buildMap(true);
return;
}
if (editScrolling) return;
var scrollTop = ui.area.view[0].scrollTop;
var lineIndex = 0;
for (var i = 0, l = scrollMap.length; i < l; i++) {
if (scrollMap[i] > scrollTop) {
break;
} else {
lineIndex = i;
}
}
var lineNo = 0;
var lineDiff = 0;
for (var i = 0, l = lineHeightMap.length; i < l; i++) {
if (lineHeightMap[i] > lineIndex) {
break;
} else {
lineNo = lineHeightMap[i];
lineDiff = lineHeightMap[i + 1] - lineNo;
}
}
var scrollInfo = editor.getScrollInfo();
var textHeight = editor.defaultTextHeight();
var posTo = 0;
var topDiffPercent = 0;
var posToNextDiff = 0;
var preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight;
var preLastLineNo = Math.round(preLastLineHeight / textHeight);
if (scrollInfo.height > scrollInfo.clientHeight && lineNo >= preLastLineNo) {
posTo = preLastLineHeight;
topDiffPercent = (scrollTop - scrollMap[preLastLineNo]) / (viewBottom - scrollMap[preLastLineNo]);
posToNextDiff = Math.ceil(textHeight * topDiffPercent);
} else {
posTo = lineNo * textHeight;
topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo]);
posToNextDiff = Math.ceil(textHeight * lineDiff * topDiffPercent);
}
editor.scrollTo(0, posTo + posToNextDiff);
preventSyncScroll = true;
viewScrolling = true; viewScrolling = true;
clearTimeout(viewScrollingTimer); clearTimeout(viewScrollingTimer);
viewScrollingTimer = setTimeout(function () { viewScrollingTimer = setTimeout(function () {
viewScrolling = false; viewScrolling = false;
}, viewScrollingDelay); }, viewScrollingDelay);
}); }
//editor.on('scroll', _.debounce(syncScrollToView, syncScrollDelay));
//ui.area.view.on('scroll', _.debounce(syncScrollToEdit, 50));
var scrollMap, lineHeightMap, viewTop, viewBottom; var scrollMap, lineHeightMap, viewTop, viewBottom;
@ -291,19 +352,12 @@ function syncScrollToView(event, _lineNo) {
if (viewScrolling) return; if (viewScrolling) return;
posTo = scrollMap[lineHeightMap[_lineNo]]; posTo = scrollMap[lineHeightMap[_lineNo]];
} }
var posDiff = Math.abs(ui.area.view.scrollTop() - posTo); ui.area.view.stop(true, true).scrollTop(posTo);
var duration = posDiff / 50; preventViewScroll = true;
ui.area.view.stop(true, true).animate({
scrollTop: posTo editScrolling = true;
}, duration >= 100 ? duration : 100, "linear"); clearTimeout(editScrollingTimer);
/* editScrollingTimer = setTimeout(function () {
if (posDiff > scrollInfo.clientHeight / 5) { editScrolling = false;
var duration = posDiff / 50; }, editScrollingDelay);
ui.area.view.stop(true, true).animate({
scrollTop: posTo
}, duration >= 100 ? duration : 100, "linear");
} else {
ui.area.view.stop(true, true).scrollTop(posTo);
}
*/
} }