4

JavaScript 範例 - scrollIntoView 實現清單自動捲動

 1 year ago
source link: https://blog.darkthread.net/blog/js-scrollintoview/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

scrollIntoView 實現清單自動捲動-黑暗執行緒

分享一個 JavaScript 小技巧,假設有個很多項目的清單,靠 CSS overflow-y: scroll 啟用垂直捲軸,除了由使用者操作上下捲動,也能用程式控制捲動到指定的一筆嗎?

用講的不容易理解,看示範就清楚吧! 在以下展示中,我用 div 當清單容器放入 16 個項目 div,清單高度只能顯示四筆,但有垂直捲軸可上下捲動,按鈕可捲動到指定項目並標示為藍底:

Fig1_638004876654520558.gif

感覺挺酷的,說穿了不值錢,其實就是用了一個所有可視元素都支援的 API - Element.scrollIntoView(),負責捲動元素所屬容器讓元素出現在可視範圍。

展示網頁的程式碼如下:線上展示

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <style>
        .container {
            width: 200px; margin: auto;
        }
        button { 
            width: 25px; padding: 0 2px;
        }
        #list {
            width: 96%; height: 92px;
            margin-top: 6px; padding: 3px;
            border: 1px solid gray;
            overflow-y: scroll;
        }
        .active {
            background-color: lightskyblue;
        }
    </style>
</head>

<body>
    <div class="container">
        <div id="buttons"></div>
        <div id="list"></div>
    </div>
    <script>
        function setFocus(no) {
            // 清除目前元素的 .active 樣式
            [].forEach.call(document.querySelectorAll('.active'), function (el) {
                el.classList.remove('active');
            });
            var line = document.getElementById('L' + no);
            line.classList.add('active');
            //捲動 line 所處容器,確保 line 元素在可視範圍
            line.scrollIntoView();
            document.getElementById('B' + no).classList.add('active');
        }
        // 在 #list div 加入 16 筆 div,並建立 16 顆連動按鈕
        for (var i = 1; i <= 16; i++) {
            var line = document.createElement('div');
            line.id = 'L' + i;
            line.textContent = 'LINE ' + i;
            document.getElementById('list').appendChild(line);
            
            var btn = document.createElement('button');
            btn.onclick = function () {
                setFocus(this.innerText);
            };
            btn.innerText = i;
            btn.id = 'B' + i;
            document.getElementById('buttons').appendChild(btn);
        }
    </script>
</body>

</html>

以上寫法在某些情境會出問題。我遇上網頁左側有個超長導覽選單的狀況,scrollIntoView() 會捲過頭:

Fig2_638004878251791153.gif

要解決其實很簡單。呼叫 scrollIntoView() 時可傳入參數的,alignTop 參數 (true/false) 指定向頂端或向底部看齊;或傳入物件參數 scrollIntoViewOptions 指定 behavior (動畫轉場採 auto 或 smooth)、block (垂直對齊依據:start/center/end/nearest,nearest 指依當下位置找最近的對齊點)、inline (水平對齊依據:start/center/end/nearset) 等參數。未傳參數時等同 alignTop = ture / scrollIntoViewOptions: { block: "start", inline: "nearest" },在這個清單捲動範例中,scrollIntoView(false) 設定 alignTop = false / scrollIntoViewOptions: { block: "end", inline: "nearest" } 即可解決。線上展示

Fig3_638004876660821866.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK