【问题标题】:Make side-by-side markdown preview scroll with its editor使用编辑器进行并排的 Markdown 预览滚动
【发布时间】:2019-01-07 23:17:36
【问题描述】:

我在左侧有一个 Markdown 编辑器,在右侧有它的 HTML 预览。

如何使预览滚动到与编辑器相同的位置。

【问题讨论】:

    标签: javascript jquery html markdown


    【解决方案1】:

    【讨论】:

    • 我为PanWriter 实现了相同的方法。希望更容易理解和更多评论。见below
    【解决方案2】:

    您链接的示例只是将滚动条对齐到相同的高度,它似乎没有对元素进行任何智能匹配。

    所以一个好的开始就是对齐滚动条。

    【讨论】:

    • 感谢您指出这一点。有没有更智能的方法来解决这个问题?这在图像繁重的文档上很容易失败。
    【解决方案3】:

    试试这个:

    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);
    

    小提琴:http://jsfiddle.net/b75KZ/5/

    不过,我不确定它是否是您想要在右侧显示的 textarea,也许是 div 来显示呈现的 html?

    如果是这样,只需将 html 中的元素和 jQuery 中的选择器更改为 var $elements = $('textarea, div#html'); 并确保为 div 设置了 id 属性。

    另外,如果您在页面上有多个 textareas 并且想要更具体,只需将选择器更改为 var $elements = $('textarea#markdown, div#html'); 并相应地更新标记,例如

    <textarea id="markdown">...</textarea>
    <div id="html">...</div>
    

    【讨论】:

      【解决方案4】:

      我已经为 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)。

      当然,您还必须以相反的方式执行此操作(滚动预览时,使编辑器滚动)并注意边缘情况/偏移,具体取决于您的布局。但这是基本算法。

      您可能希望将其包装在 _.throttle 之类的东西中。

      【讨论】:

        猜你喜欢
        • 2011-04-18
        • 1970-01-01
        • 2011-10-06
        • 2016-01-20
        • 2021-07-31
        • 1970-01-01
        • 2020-09-09
        • 1970-01-01
        • 2018-04-22
        相关资源
        最近更新 更多