使用其编辑器并排降价预览滚动
Make side-by-side markdown preview scroll with its editor
我在左侧有一个 Markdown 编辑器,在右侧有它的 HTML 预览。
如何使预览滚动到与编辑器相同的位置。
您链接的示例只是将滚动条对齐到相同的高度,它似乎没有对元素进行任何智能匹配。
所以一个好的开始就是对齐滚动条。
Remarkable library use a complex scroll sync for the demo : https://github.com/jonschlinkert/remarkable/blob/dev/demo/assets/index.js#L213
试试这个:
var $elements = $('textarea');
var sync = function(e){
var $other = $elements.not(this).off('scroll'), other = $other.get(0);
var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight);
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
setTimeout( function(){ $other.on('scroll', sync ); },10);
}
$elements.on( 'scroll', sync);
Fiddle: http://jsfiddle.net/b75KZ/5/
尽管如此,我不确定它是否是您想要在右边的 textarea
,也许是 div
来显示呈现的 html?
如果是这样,只需将 html 中的元素和 jQuery 中的选择器更改为 var $elements = $('textarea, div#html');
并确保为 [= 设置了 id
属性13=].
此外,如果您在页面上有多个 textarea
并且想要更具体,只需将选择器更改为 var $elements = $('textarea#markdown, div#html');
并相应地更新标记,例如
<textarea id="markdown">...</textarea>
<div id="html">...</div>
我已经为 PanWriter 实现了这个。
来自this commit的要点:
var editor = ... // a CodeMirror editor instance
var frameWindow = document.querySelector('iframe').contentWindow; // my preview frame
var scrollMap;
editor.on("scroll", function() {
if (!scrollMap) {
buildScrollMap(editor, 10);
}
frameWindow.scrollTo(0, scrollMap[scrollTop]);
});
function buildScrollMap(editor, editorOffset) {
// scrollMap maps source-editor-line-offsets to preview-element-offsets
// (offset is the number of vertical pixels from the top)
scrollMap = [];
scrollMap[0] = 0;
// lineOffsets[i] holds top-offset of line i in the source editor
var lineOffsets = [undefined, 0]
, knownLineOffsets = []
, offsetSum = 0
;
editor.eachLine( function(line) {
offsetSum += line.height;
lineOffsets.push(offsetSum);
});
var lastEl;
frameWindow.document.querySelectorAll('body > [data-source-line]').forEach( function(el){
// for each element in the preview with source annotation
var line = parseInt(el.getAttribute('data-source-line'), 10)
, lineOffset = lineOffsets[line]
;
// fill in the target offset for the corresponding editor line
scrollMap[lineOffset] = el.offsetTop - editorOffset;
knownLineOffsets.push(lineOffset)
lastEl = el;
});
if (lastEl) {
scrollMap[offsetSum] = lastEl.offsetTop + lastEl.offsetHeight;
knownLineOffsets.push(offsetSum);
}
// fill in the blanks by interpolating between the two closest known line offsets
var j = 0;
for (var i=1; i < offsetSum; i++) {
if (scrollMap[i] === undefined) {
var a = knownLineOffsets[j]
, b = knownLineOffsets[j + 1]
;
scrollMap[i] = Math.round(( scrollMap[b]*(i - a) + scrollMap[a]*(b - i) ) / (b - a));
} else {
j++;
}
}
}
为此,您需要在 HTML 输出上添加源代码行注释(例如使用 markdown-it-source-map)。
当然,您还必须以相反的方式进行操作(当您滚动预览时,使编辑器滚动)并根据您的布局寻找 edge-cases/offset。但这是基本算法。
你可能想用 _.throttle.
之类的东西包装它
我在左侧有一个 Markdown 编辑器,在右侧有它的 HTML 预览。
如何使预览滚动到与编辑器相同的位置。
您链接的示例只是将滚动条对齐到相同的高度,它似乎没有对元素进行任何智能匹配。
所以一个好的开始就是对齐滚动条。
Remarkable library use a complex scroll sync for the demo : https://github.com/jonschlinkert/remarkable/blob/dev/demo/assets/index.js#L213
试试这个:
var $elements = $('textarea');
var sync = function(e){
var $other = $elements.not(this).off('scroll'), other = $other.get(0);
var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight);
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
setTimeout( function(){ $other.on('scroll', sync ); },10);
}
$elements.on( 'scroll', sync);
Fiddle: http://jsfiddle.net/b75KZ/5/
尽管如此,我不确定它是否是您想要在右边的 textarea
,也许是 div
来显示呈现的 html?
如果是这样,只需将 html 中的元素和 jQuery 中的选择器更改为 var $elements = $('textarea, div#html');
并确保为 [= 设置了 id
属性13=].
此外,如果您在页面上有多个 textarea
并且想要更具体,只需将选择器更改为 var $elements = $('textarea#markdown, div#html');
并相应地更新标记,例如
<textarea id="markdown">...</textarea>
<div id="html">...</div>
我已经为 PanWriter 实现了这个。
来自this commit的要点:
var editor = ... // a CodeMirror editor instance
var frameWindow = document.querySelector('iframe').contentWindow; // my preview frame
var scrollMap;
editor.on("scroll", function() {
if (!scrollMap) {
buildScrollMap(editor, 10);
}
frameWindow.scrollTo(0, scrollMap[scrollTop]);
});
function buildScrollMap(editor, editorOffset) {
// scrollMap maps source-editor-line-offsets to preview-element-offsets
// (offset is the number of vertical pixels from the top)
scrollMap = [];
scrollMap[0] = 0;
// lineOffsets[i] holds top-offset of line i in the source editor
var lineOffsets = [undefined, 0]
, knownLineOffsets = []
, offsetSum = 0
;
editor.eachLine( function(line) {
offsetSum += line.height;
lineOffsets.push(offsetSum);
});
var lastEl;
frameWindow.document.querySelectorAll('body > [data-source-line]').forEach( function(el){
// for each element in the preview with source annotation
var line = parseInt(el.getAttribute('data-source-line'), 10)
, lineOffset = lineOffsets[line]
;
// fill in the target offset for the corresponding editor line
scrollMap[lineOffset] = el.offsetTop - editorOffset;
knownLineOffsets.push(lineOffset)
lastEl = el;
});
if (lastEl) {
scrollMap[offsetSum] = lastEl.offsetTop + lastEl.offsetHeight;
knownLineOffsets.push(offsetSum);
}
// fill in the blanks by interpolating between the two closest known line offsets
var j = 0;
for (var i=1; i < offsetSum; i++) {
if (scrollMap[i] === undefined) {
var a = knownLineOffsets[j]
, b = knownLineOffsets[j + 1]
;
scrollMap[i] = Math.round(( scrollMap[b]*(i - a) + scrollMap[a]*(b - i) ) / (b - a));
} else {
j++;
}
}
}
为此,您需要在 HTML 输出上添加源代码行注释(例如使用 markdown-it-source-map)。
当然,您还必须以相反的方式进行操作(当您滚动预览时,使编辑器滚动)并根据您的布局寻找 edge-cases/offset。但这是基本算法。
你可能想用 _.throttle.
之类的东西包装它