1. 程式人生 > 其它 >隨心所欲的滾動條,遠離產品汪(一)

隨心所欲的滾動條,遠離產品汪(一)

在我們的開發生活中,相信很多人都會遇到形形色色的專案需求,比如更改瀏覽器的預設樣式,在產品定下需求後給的網頁設計圖中我們最常遇到的是自定義滾動條的樣式,或者當你想構建一個很有特色和創意的網頁,那麼也肯定希望自己能夠去設定滾動條樣式,當然,做好準備才是最重要的,最近在專案中遇到了,正好來總結一下。

本文主要內容

1.基本原理圖

2.結構佈局分析

3.功能實現邏輯

4.實現步驟

5.小結

1.基本原理圖

大家可以先根據原理圖自己分析一波,有利於加深對下文的理解

2. 結構佈局分析

我們在開發專案中會時不時的碰到這種情況,當滾動塊B超出了父級可視部分,我們總會設定overflow的屬性值來隱藏超出的部分,根據預設的滾動條來操作隱藏區的內容,當將可視區A設定overflow:auto時,網頁會顯示出預設的滾動條樣式。

如圖下所示,初始滾動條的效果:

此時我們會發現,有些時候設計師給出的設計圖滾動條的樣式是不同的或者預設的滾動條樣式會影響到我們對網頁的整體感覺,所以我們需要隱藏預設滾動條,將可視區設定為overflow:hidden,自己去重新設定滾動條的樣式。

首先根據原理圖,我們寫出基本結構程式碼:

<body>
   <div class="wrap">
      <div class="con" id = "bx">//可視區A
         <p id="cn"> //滾動塊B
            滾動塊B內容
          </p>  
       </div>
       <div class="boxscr" id = "bs">//滾動條滾動區
          <div class="scr" id = "sc"></div> //滾動條
       </div>
    </div>
</body>

根據滾動條的上下滾動方式,我們可以想到可以通過控制margin-top和top的值來實現滾動條的滾動,本文中通過使用定位的方式來實現。

接下來我們完善具體的樣式結構:

<!DOCTYPE html>
<html>
    <head>
        <title>自定義滾動條</title>
        <meta charset="utf-8">
        <style type="text/css">
.wrap {
            width: 200px;
            height: 150px;
            margin: 0 auto;
        }
        .con {
            float: left;
            overflow: auto;
            width: 180px;
            height: 150px;
            background: #39f;
        }
        .con p {
            margin: 0;
            color: #fff;
            text-align: center;
            line-height: 20px;
            font-size: 14px;
        }
        .boxscr {
            float: right;
            position: relative;
            width: 20px;
            height: 150px;
            background: #d9ecff;
        }
        .scr {
            position: absolute;
            width: 20px;
            border-radius: 10px;
            background: #c6ccff;
            cursor: pointer;
        }
    </style>
    </head>
    <body>
        <div class="wrap">
            <div class="con" id = "bx">
                <p id="cn">
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                    HTML5學堂-自定義滾動條
                </p>  
            </div>
            <div class="boxscr" id = "bs">
                <div class="scr" id = "sc"></div>
            </div>
        </div>
    </body>
</html>

實現的效果:

ps:當前的效果樣式只是個示例,大家可以根據自己的實際需求進行樣式調整。

3. 功能實現邏輯

1. 通過控制滾動條的top值來實現滾動條的上下滾動,但是滾動塊的內容有限,滾動條不可能無限滾動,所以滾動條有著自己的滾動範圍。

2. 同理,滾動塊B則通過可視區A的scrollTop來控制上下滾動,當然也有著自己的滾動範圍。

3. 如何將兩者關聯起來呢,實際上細心的你已經發現:滾動條C的高度/滾動區D的高度 = 可視區A的高度/ 滾動塊B的高度,即滾動塊的滾動距離和滾動條的滾動距離它們的比都是存在聯絡的。

現在我們分幾個步驟來實現它們。

4. 實現步驟

此處我們先上程式碼,然後根據程式碼來進行具體分析:

<script>
    var bx = document.getElementById("bx"),
        cn = document.getElementById("cn"),
        bs = document.getElementById("bs"),
        sc = document.getElementById("sc"),


        oldY = 0,      //滑鼠初次點選的Y軸座標
        newY = 0,      // 滑鼠拖動時的Y軸座標
        nowY = 0,      // 滑鼠拖動時滾動條C距父級頂部的高度
        maxY = 0,      // 拖動的最大極限值
        nowDisY = 0,   // 點選滾動條C時距父級頂部的高度


        bxHeight = bx.clientHeight,  // 可視區A高度
        bsHeight = bs.clientHeight, //  滾動區D高度
        cnHeight = cn.offsetHeight;  // 滾動塊B的高度


        // 根據滾動塊B實際內容高度控制滾動條C的高度
        scHeight = bxHeight/cnHeight * bxHeight;
        sc.style.height = scHeight + "px";  


        // 當滾動塊B實際高度小於可視區時,滾動條隱藏
        if (cnHeight < bxHeight) {
            bs.style.display = "none";
        };


        sc.onmousedown = function(e) {
            oldY = e.clientY;
            nowDisY = sc.offsetTop;         // 當前的滾動條C的top值
            e.preventDefault();
            document.onmousemove = function(e) {
                newY = e.clientY;
                nowY = nowDisY + newY - oldY;  // 拖動後的滾動條C的top值
                maxY = bsHeight - scHeight;    // 設定滾動條top極限值


                if (nowY <= 0) {
                    nowY = 0;
                };
                if (nowY >= maxY) {
                    nowY = maxY;
                };


            bx.scrollTop = nowY/maxY * (cnHeight - bxHeight);  // 設定滾動塊B的scrollTop值
            sc.style.top = nowY + "px";
            }
        }
        document.onmouseup = function() {
            document.onmousemove = null;   
        }
</script>

a) 計算滾動條高度

因為滾動條C的高度不是一成不變的,需要滾動塊B的實際高度與可視區A高的相似比來計算。

即:滾動塊B的高/可視區A的高 = 滾動區D的高/滾動條C的高

scHeight = bxHeight/cnHeight * bxHeight;// 根據滾動塊B實際內容高度控制滾動條C的高度
sc.style.height = scHeight + "px";  

b) 滑鼠拖動時的座標位置

無論開始滑鼠點選滾動條哪一個位置,都將視為點選滾動條的頂點座標。

即:滾動條的滾動距離 = 拖動後滑鼠變化的Y值 – 點選時滑鼠獲取的Y值

nowY = nowDisY + newY - oldY;  // 拖動後的滾動條C的top值

c) 實現滾動條拖動

在實現滾動條拖動的同時,我們並不能忽視滾動條的當前位置,當二次拖動時,此時的滾動條或許已經偏離了初始位置。

即: 當前滾動條位置的top值 = 拖動後滑鼠變化的Y值 – 點選時滑鼠獲取的Y值 + 初始滾動條的top值

nowY = nowDisY + newY - oldY;  // 拖動後的滾動條C的top值

d) 限制滾動條的拖動範圍

滾動條有著自己的活動範圍,即滾動條的top值有著自己的極限距離,當超過了極限距離,此時的top值就一直等於這個值,反之最小值也是如此,那麼這個值是多少呢?

由原理圖可知:0 <= 滾動條的top值 <= 滾動區D的高度 – 滾動條C的高度

maxY = bsHeight - scHeight;    // 設定滾動條top極限值
if (nowY <= 0) {
   nowY = 0;
};
if (nowY >= maxY) {
   nowY = maxY;
};

e) 所有東西都準備好了,怎麼讓滾動條C的滾動控制到滾動塊B呢

首先我們需要知道,滾動塊B可滾動的極限值,即可視區A的高 – 滾動塊B的高。 滾動塊B的滾動距離與滾動條C的滾動距離相呼應。

即: 可視區A的scrollTop = 頂點可移動極限值 * 滾動條滾動的比值

bx.scrollTop = nowY/maxY * (cnHeight - bxHeight);  // 設定滾動塊B的scrollTop值
sc.style.top = nowY + "px";

這個時候,重新整理下網頁,就可以發現滾動條已經可以滾動了,同時也控制著內容區的滑動。

5.小結

自定義滾動條是基於拖拽的原理實現的,在學堂官網中,大家可以找到“拖拽”的相關知識去進一步鞏固瞭解,回到當前,大家有沒有發現還存在一些不好的地方呢?

1. 每次滾動都需要拖拽,很累啊,為什麼滑鼠滾輪不能用?

2. 並沒有到考慮相容問題。

由於篇幅原因,這裡不再進行說明,將在下週同一時間更新自定義滾動條的續篇,著重為大家介紹滾輪事件的新增及相容問題的解決。

本文系HTML5學堂獨家內容,轉載請在文章開頭顯眼處註明作者和出處“HTML5學堂(http://www.h5course.com/)”