您好,登錄后才能下訂單哦!
這篇“怎么使用JavaScript markdown編輯器實(shí)現(xiàn)雙屏同步滾動”文章的知識點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么使用JavaScript markdown編輯器實(shí)現(xiàn)雙屏同步滾動”文章吧。
假設(shè)現(xiàn)在正在滾動 a 屏,那 a 屏的滾動百分比計(jì)算方式為:a 屏的滾動高度 / a 屏的內(nèi)容總高度
,用代碼表示 a.scrollTop / a.scrollHeight
。當(dāng)滾動 a 屏?xí)r,需要手動同步 b 屏的滾動高度,也就是根據(jù) a 屏的滾動百分比算出 b 屏的滾動高度:
a.onscroll = () => { b.scrollTo({ top: a.scrollTop / a.scrollHeight * b.scrollHeight }) }
原理就是這么簡單,可惜實(shí)現(xiàn)效果不太好。
雙屏內(nèi)容高度不一致,是因?yàn)?markdown 同一個(gè)元素渲染后的高度和渲染前會有差別。例如一個(gè)圖片,用 markdown 寫就一行代碼的事,但渲染出來的圖片有大有小,高度幾十、幾百像素的都有。如果 markdown 的圖片代碼雙屏同時(shí)渲染,倒是能解決這個(gè)問題。
但是除了圖片仍然有不少元素渲染前后的高度是有差距的,雖然沒有圖片這么夸張。譬如 h2 h3 這種,當(dāng)文章內(nèi)容越長,這種小差異帶來的問題會越來越大,導(dǎo)致雙屏內(nèi)容高度的差距也會越來越大。所以說這種方案也不是很靠譜。
每一行的元素都賦上一個(gè)索引,根據(jù)索引來精確精確同步每一行的滾動高度
之前兩個(gè)方案都屬于勉強(qiáng)能用,不夠好?,F(xiàn)在這個(gè)第三方案就比前面兩個(gè)強(qiáng)多了,幾乎能做到精確同步每一行的內(nèi)容。具體怎么做呢?
第一步,監(jiān)聽 markdown 編輯框的內(nèi)容變化,為每一個(gè)元素賦上一個(gè)索引,空行空文本除外。
當(dāng)把編輯框的 HTML 傳給右邊的框渲染時(shí),需要把 data-index
賦值給渲染后的元素。這樣就能通過 data-index
精確定位渲染前后的同一元素了。
第二步,根據(jù) a 屏的元素滾動高度計(jì)算 b 屏上同一索引的元素滾動高度
在 a 屏進(jìn)行滾動時(shí),需要從上到下遍歷 a 屏的所有元素,并且找到第一個(gè)在屏幕內(nèi)的元素。找到第一個(gè)在屏幕內(nèi)的元素
這句話的意思是因?yàn)樵跐L動過程中,有些元素會因?yàn)闈L動跑到屏幕外面(原來在屏幕內(nèi),滾動到屏幕外),這些元素我們是不需要計(jì)算的。
判斷一個(gè)元素是否在屏幕內(nèi):
// dom 是否在屏幕內(nèi) function isInScreen(dom) { const { top, bottom } = dom.getBoundingClientRect() return bottom >= 0 && top < window.innerHeight }
除了判斷元素是否在屏幕內(nèi),還需要判斷這個(gè)元素在屏幕內(nèi)的部分占整個(gè)元素高度的百分比。譬如說一個(gè)圖片的 markdown 字符串,由于滾動的原因,導(dǎo)致一半在屏幕內(nèi),一半在屏幕外。為了精確同步,那么渲染后的圖片也必須有一半在屏幕內(nèi)一半在屏幕外。
計(jì)算元素在屏幕內(nèi)的百分比代碼:
// dom 在當(dāng)前屏幕展示內(nèi)容的百分比 function percentOfdomInScreen(dom) { // 已經(jīng)通過另一個(gè)函數(shù) isInScreen() 確定了這個(gè) dom 在屏幕內(nèi),所以只需要計(jì)算它在屏幕內(nèi)的百分比,而不需要考慮它是否在屏幕外 const { height, bottom } = dom.getBoundingClientRect() if (bottom <= 0) return 0 // 不在屏幕內(nèi) if (bottom >= height) return 1 // 完全在屏幕內(nèi) return bottom / height // 部分在屏幕內(nèi) }
現(xiàn)在我們就可以從上到下遍歷 a 屏的所有元素,找到第一個(gè)在屏幕內(nèi)的元素了:
// scrollContainer 即上面說的 a 屏,ShowContainer 是 b 屏 const nodes = Array.from(scrollContainer.children) for (const node of nodes) { // 從上往下遍歷,找到第一個(gè)在屏幕內(nèi)的元素 if (isInScreen(node) && percentOfdomInScreen(node) >= 0) { const index = node.dataset.index // 根據(jù)滾動元素的索引,找到它在渲染框中對應(yīng)的元素 const dom = ShowContainer.querySelector(`[data-index="${index}"]`) // 獲取滾動元素在 a 屏中展示的內(nèi)容百分比 const percent = percentOfdomInScreen(node) // 計(jì)算這個(gè)對等元素在 b 屏中距離容器頂部的高度 const heightToTop = getHeightToTop(dom) // 根據(jù) percent 算出對等元素在 b 屏中需要隱藏的高度 const domNeedHideHeight = dom.offsetHeight * (1 - percent) // scrollTo({ top: heightToTop }) 會把對等元素滾動到在 b 屏中恰好完全展示整個(gè)元素的位置 // 然后再滾動它需要隱藏的高度 domNeedHideHeight,組合起來就是 scrollTo({ top: heightToTop + domNeedHideHeight }) ShowContainer.scrollTo({ top: heightToTop + domNeedHideHeight }) break } }
有一些元素渲染后會變成嵌套元素,例如表格 table,渲染后的內(nèi)容層級為:
<table> <tbody> <tr> <td></td> </tr> </tbody> </table>
按照目前的渲染邏輯,假如我寫了個(gè)表格:
|1|b| ...
那么 |1|b|
上的 data-index
會對應(yīng)到 table
上。
那這就會有個(gè) bug,當(dāng) |1|b|
滾動到 50% 的時(shí)候,整個(gè) table
也會滾動到 50%。
這個(gè)現(xiàn)象如下圖所示:
這和我們相要的效果不一樣。a 屏連一行的內(nèi)容都沒滾完,b 屏整個(gè)內(nèi)容已經(jīng)滾動到一半了。
所以像這種嵌套的元素,在打 data-index
標(biāo)記時(shí),要把它打到真正的內(nèi)容上。用表格 table 來做示例,就得把 data-index
的標(biāo)記打在 tr
上。
這樣一來,同步滾動就正常了。同理,其他的嵌套元素也一樣(譬如 ul ol)。
以上就是關(guān)于“怎么使用JavaScript markdown編輯器實(shí)現(xiàn)雙屏同步滾動”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。