簡書 Markdown 預(yù)覽同步滾動腳本


2019.1.22 簡書官方已經(jīng)加入了同步滾動的功能北发。
但是官方實(shí)現(xiàn)的時(shí)候员串,優(yōu)先的是頂端對齊,也就是編輯區(qū)和預(yù)覽區(qū)在頂部一定是同步的壕曼。本文的實(shí)現(xiàn)是優(yōu)先底部對齊苏研,也就是如果滑動到最后,預(yù)覽和編輯是一定會對齊的腮郊。我覺得優(yōu)先底部對齊更實(shí)用摹蘑,因?yàn)閷懽鞯倪^程中在文末添加內(nèi)容的場景更多,這個(gè)時(shí)候需要對齊轧飞。


如你所見衅鹿,右側(cè)的預(yù)覽并不能實(shí)時(shí)地與左側(cè)的輸入進(jìn)行同步。

這是很氣的过咬。
哎呦這是最氣的大渤。

所以我寫了一個(gè)腳本,點(diǎn)擊此處安裝(需要先行安裝瀏覽器用戶腳本擴(kuò)展)掸绞。

使用效果

經(jīng)過評論區(qū)小伙伴的反饋泵三,這里還真遇到一個(gè)坑:
一開始的版本做的比較簡單,當(dāng)輸入框接收到滾動事件后,就直接向預(yù)覽框也發(fā)送這個(gè)滾動事件烫幕。
但是當(dāng)瀏覽器開啟平滑滾動時(shí)俺抽,一次鼠標(biāo)滾輪的滾動會被瀏覽器分解成多段來處理,以達(dá)到平滑的效果较曼。
平滑滾動的情況下磷斧,被分解的滾動事件的頭一段的像素移動非常小,我們的腳本卻會把這個(gè)小滾動事件也照舊作用在預(yù)覽框上捷犹。問題來了弛饭,此時(shí)預(yù)覽框接收到滾動事件后,又通過我們這個(gè)腳本向輸入框上發(fā)了一個(gè)小滾動事件伏恐,相當(dāng)于“反彈”了一下孩哑。也就是說,如果沒有這個(gè)“反彈”回來的滾動事件影響翠桦,預(yù)覽框本應(yīng)該繼續(xù)進(jìn)行接下來的平滑滾動分解動作横蜒,但是卻收到了來自我們腳本的小滾動事件,就忽視了接下來的平滑滾動分解動作销凑,所以每次滾動只滾動了很小的距離丛晌,看起來像是被卡住了。
所以問題在于考慮的太簡單斗幼,事件發(fā)生了來回相互觸發(fā)澎蛛。我們的腳本無法區(qū)別哪些是人產(chǎn)生的滾動事件,哪些是腳本發(fā)出的滾動事件蜕窿,導(dǎo)致事件來回反彈谋逻,影響正常工作。

解決辦法是手動的截?cái)嘤晌覀兊哪_本所產(chǎn)生的滾動事件桐经。步驟如下:
假如發(fā)生了編輯框的滾動事件計(jì) mainFlag 為 true毁兆,發(fā)生了預(yù)覽框的滾動事件計(jì) preFlag 為 true。

  1. 用戶滾動編輯框阴挣,觸發(fā)滾動事件气堕, mainFlag 計(jì)為 true,觸發(fā)腳本改變預(yù)覽框位置畔咧。
  2. 上一步驟預(yù)覽框位置改變又觸發(fā)了預(yù)覽框滾動事件茎芭, preFlag 計(jì)為 true,此時(shí)檢測發(fā)現(xiàn) mainFlag 也為 true誓沸,證明這次預(yù)覽框滾動事件是由腳本產(chǎn)生的事件梅桩,應(yīng)該被截?cái)唷#ㄈ绻唤財(cái)喟菟恚@次滾動事件又會觸發(fā)更改編輯框的動作宿百,引起 bug煮寡。)
  3. 把兩個(gè)標(biāo)志位都恢復(fù)為 false

形象的說就是犀呼,由兩個(gè)標(biāo)志位來做“配對”,“配對”抵消下一個(gè)事件薇组。


1.3 版代碼如下:

// ==UserScript==
// @name            簡書 Markdown 預(yù)覽同步滾動
// @name:en         Jianshu MD AUTO Scroll
// @namespace       https://github.com/BlindingDark/JianshuMDAutoScroll
// @include         *://www.reibang.com/writer*
// @version         1.3
// @description:en  jianshu Markdown preview AUTO scroll
// @description     給簡書的在線 Markdown 編輯器增加輸入預(yù)覽同步滾動的功能
// @author          BlindingDark
// @grant           none
// @require      https://cdn.bootcss.com/jquery/3.2.1/jquery.js
// ==/UserScript==

(function() {
  'use strict';
  var spSwitchMain; // 切換的那個(gè)按鈕所在的窗體
  var txtMain;      // 輸入框
  var spPreview;    // 預(yù)覽框

  const SWITCH_FEATURE   = 'a.fa.fa-columns';
  const EXPAND_FEATURE   = 'a.fa.fa-expand';
  const COMPRESS_FEATURE = 'a.fa.fa-compress';

  function getInput() {
    return $('#arthur-editor');
  }

  function getPreview() {
    return getInput().closest("div").parent().next();
  }

  function scrollEvent(){
    txtMain = getInput()[0];
    spPreview = getPreview()[0];

    if(txtMain == undefined) {
      return;
    }
    if(spPreview == undefined) {
      return;
    }

    let mainFlag = false; // 抵消兩個(gè)滾動事件之間互相觸發(fā)
    let preFlag = false; // 如果兩個(gè) flag 都為 true外臂,證明是反彈過來的事件引起的

    function scrolling(who){
      if(who == 'pre'){
        preFlag = true;
        if (mainFlag === true){ // 抵消兩個(gè)滾動事件之間互相觸發(fā)
          mainFlag = false;
          preFlag = false;
          return;
        }
        txtMain.scrollTop = Math.round((spPreview.scrollTop + spPreview.clientHeight) * txtMain.scrollHeight  / spPreview.scrollHeight - txtMain.clientHeight);
        return;
      }
      if(who == 'main'){
        mainFlag = true;
        if (preFlag === true){ // 抵消兩個(gè)滾動事件之間互相觸發(fā)
          mainFlag = false;
          preFlag = false;
          return;
        }
        spPreview.scrollTop = Math.round((txtMain.scrollTop + txtMain.clientHeight) * spPreview.scrollHeight / txtMain.scrollHeight - spPreview.clientHeight);
        return;
      }
    }

    function mainOnscroll(){
      scrolling('main');
    }

    function preOnscroll(){
      scrolling('pre');
    }

    getInput().on('scroll', () => mainOnscroll());
    getPreview().on('scroll', () => preOnscroll());
  }

  function cycle() {
    scrollEvent();
    $(EXPAND_FEATURE).on('click', scrollEvent);
    $(COMPRESS_FEATURE).on('click', scrollEvent);
    $(SWITCH_FEATURE).on("click", scrollEvent);

    window.setTimeout(cycle, 1000);
  }

  cycle();
})();

有興趣的同學(xué)可以直接前往 Github 改進(jìn)此腳本。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末律胀,一起剝皮案震驚了整個(gè)濱河市宋光,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炭菌,老刑警劉巖罪佳,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異黑低,居然都是意外死亡赘艳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門克握,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蕾管,“玉大人,你說我怎么就攤上這事菩暗£” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵停团,是天一觀的道長旷坦。 經(jīng)常有香客問我,道長佑稠,這世上最難降的妖魔是什么秒梅? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮讶坯,結(jié)果婚禮上番电,老公的妹妹穿的比我還像新娘。我一直安慰自己辆琅,他們只是感情好漱办,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著婉烟,像睡著了一般娩井。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上似袁,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天洞辣,我揣著相機(jī)與錄音咐刨,去河邊找鬼。 笑死扬霜,一個(gè)胖子當(dāng)著我的面吹牛定鸟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播著瓶,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼联予,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了材原?” 一聲冷哼從身側(cè)響起沸久,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎余蟹,沒想到半個(gè)月后卷胯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡威酒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年窑睁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葵孤。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卵慰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出佛呻,到底是詐尸還是另有隱情裳朋,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布吓著,位于F島的核電站鲤嫡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏绑莺。R本人自食惡果不足惜暖眼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纺裁。 院中可真熱鬧诫肠,春花似錦、人聲如沸欺缘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谚殊。三九已至丧鸯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嫩絮,已是汗流浹背丛肢。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工围肥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜂怎。 一個(gè)月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓穆刻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杠步。 傳聞我的和親對象是個(gè)殘疾皇子蛹批,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,734評論 25 707
  • 陽光公寓門口有一條斑馬線,它沒有紅綠燈篮愉,卻鏈接著陽光胡同和國泰商廈。 每天上班高峰期差导,都必須經(jīng)過這一條路试躏。路上車水...
    花落風(fēng)吹雪閱讀 329評論 0 0