創意!原來阮大佬博客的閲讀進度功能這麼簡單

語言: CN / TW / HK

大廠技術    高級前端    Node進階

點擊上方  程序員成長指北 ,關注公眾號

回覆 1 ,加入高級Node交流羣

:christmas_tree: 前言

小包在學習阮一峯大佬的《ES6入門教程》時,對文章頂部的 閲讀進度 功能產生了濃厚的興趣。小包當時猜想應該是使用 JavaScript 實現的,但最近愛上了浩如煙海的 CSS ,於是小包有個大膽的想法,單純的 CSS 能實現閲讀進度功能嗎?

能,不止能,還非常巧妙! CSS:star:CSS:star:CSS 真的太強了。

雖然通過 CSS 可以實現閲讀進度問題,但 JavaScript 作為老本行,一樣得精通。

因此學習本文,你可以學會:

  • 使用 JavaScript 實現閲讀進度功能
  • 使用 CSS 實現閲讀進度功能

:fire: 利用JavaScript實現閲讀進度

:page_with_curl: HTML與CSS

html css 部分非常簡單,通過嵌套的兩個 div 實現,外部的 div 提供底色背景,內部 div 顯示閲讀進度

<div class="read_pro">
    <div class="read_pro_inner"></div>
</div>
複製代碼
.read_pro {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    background-color: #DDD;
}
.read_pro_inner {
    content: '';
    position: absolute;
    left: 0;
    height: 100%;
    background-color: #0089f2;
}
複製代碼

當我們設置 .read_pro_inner 的寬度為 20% 時,得到的效果圖如下:

read_pro_js.png

只截取部分圖,並放大了瀏覽器,要不灰色部分會非常長

台子搭好了,下面就是通過 js 來動態計算 read_pro_innerwidth 即可。

:clapper: JS實現

如果我們利用 JavaScript 來實現閲讀進度,我們要獲取到文檔的總高度、文檔滾動距離、瀏覽器窗口的可視高度。

  • 文檔總高度: document.documentElement.scrollHeight
  • 窗口可視高度: document.documentElment.cliengHeight
  • 滾動距離: document.documentElement.scrollTop || document.body.scrollTop

光看上面三個屬性的名字有幾分難以理解,來看一張示意圖

scroll.jpg

從上圖可以看到 scrollTop 就是已經讀過被捲起來的文檔部分, scrollHeight 是文檔的總長度, clientHeight 是瀏覽器顯示區域的高度

圖源: 慕課手記 [2]

獲取上面幾個屬性值後,閲讀進度就可以通過下面的公式計算出來

readProInner.style.width = +(scrollTop / (scrollHeight- clientHeight)).toFixed(2)*100 + '%'
複製代碼

大家可能會有疑惑,為什麼分母是 scrollHeight- clientHeight 而不是 scrollHeight ?

當滾動條滾動到底部時,瀏覽器此時仍顯示一屏內容,此時滾動條無法再滾動, scrollTop 無法再增加,因此 scrollTop 的最大值是 scrollHeight- clientHeight ,如果使用 scrollHeight 做分母,閲讀進度最終無法達到 100%

document.addEventListener('scroll', function(e) {
    const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    readProInner.style.width = +(scrollTop/(scrollHeight-clientHeight)).toFixed(2)*100 + '%'
})
複製代碼

使用 js 實現需要監聽 scroll 事件,而且滾動時有可能是頻繁的 scroll 事件觸發,有可能會造成一定的性能浪費,所以我們來一起學習 css 實現方案

:star2: 使用CSS實現閲讀進度

使用 CSS 實現閲讀進度的方法很有意思,而且非常巧妙,不多説了,一起來看看。

:closed_book:預備知識

  1. linear-gradient : 線性漸變,第一個參數為漸變方向,後面是顏色比例變化。

    比如設置 linear-gradient(to right top, #0089f2 50%, #DDD 50%)

    就可以實現下面效果,一個藍色的三角形:

    body-linear.png

    看到這種藍色的三角形,你有沒有感覺離閲讀進度已經很近了?

    如果我們用一塊白塊遮住藍塊,只留一條縫在頂部,那當前顯示出來藍色塊的底邊不就是閲讀進度嗎?

    scrollPro.gif

    最後處理最後一屏的問題,保證滾動條滾動至底部時,閲讀進度到達 100%

    scrollBottom.png

    這裏如果沒能理解原理,不用急,後面我會更詳細的演示

  2. @supports

類似於 js 的功能檢查,可以檢查 CSS 中某一屬性或功能當前瀏覽器是否支持。

:bulb: 實現原理

上面講解 linear-height 時,我們提出了一種實現方案: 使用一塊白塊遮住藍塊,只留一條縫在頂部,顯示的藍條長度就是閲讀進度

光説不難假把式,為了方便大家理解原理,我們使用一個案例來模擬一下,藍塊仍保持原來大小,使用一塊 0.8 透明度的黑塊蓋在上面,黑塊給藍塊在頂部空出 10px 空間。具體看下面演示

scrollShow.gif

現在是不是感覺瞬間茅塞頓開

:computer: CSS實現

  1. 首先使用 `linear-gradient` 實現藍色背景塊,並且要空出最後一屏
    
body{ 
    background: linear-gradient(to right top, #0089f2 50%, #DDD 50%);
    /* 通過 calc 函數配合 100vh 就可以從總長中刪除一屏的高度 */
    /* 100vh 瀏覽器視口的高度 */
    background-size: 100% calc(100% - 100vh + 4px);
    background-repeat: no-repeat;
}

複製代碼
  1. 設置蓋住藍塊的白塊

閲讀進度條的高度為 3px ,因此設置白塊的高度為 100% \- 3px ,可以另外加一個 div 元素來設置白塊,但小包推薦使用為元素 :before/:after ,偽元素不在文檔流之中,方便渲染和控制

body:before{
    content:'';
    /* fixed定位 */
    position: fixed;
    /* 同時設置 top 和 bottom 可以拉伸 height */
    /* 設置高度為 100% - 3px */
    top: 3px;
    bottom: 0;
    width: 100%;
    /* 降低層級,白塊顯示在文字之下 */
    z-index: -1;
    background: white;
}
複製代碼

通過上面簡單的代碼,就可以實現封面閲讀進度效果了,撒花~~~~

源碼倉庫

傳送門: 閲讀進度功能 [3]

如果感覺有幫助的話,別忘了給小包點個 :star: 。

關於本文

作者:戰場小包

https://juejin.cn/po st/7033668584026931214

Node 社羣

我組建了一個氛圍特別好的 Node.js 社羣,裏面有很多 Node.js小夥伴,如果你對Node.js學習感興趣的話(後續有計劃也可以),我們可以一起進行Node.js相關的交流、學習、共建。下方加 考拉 好友回覆「Node」即可。

如果你覺得這篇內容對你有幫助,我想請你幫我2個小忙:

1. 點個 「在看」 ,讓更多人也能看到這篇文章

2. 訂閲官方博客  www.inode.club  讓我們一起成長

點贊和在看就是最大的支持 :heart: