創意!原來阮大佬部落格的閱讀進度功能這麼簡單

語言: 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: