背景
在很久以前,有寫過一個使用 js 實作單張圖片持續滾動圖片的 代碼,但那一版實作會持續操作DOM,向DOM中插入元素,性能較差,最近發現 requestAnimationFrame 通過 影片的方式實作圖片滾動更加方便,遂重新實作了一版,效果更贊,性能更好,
效果如下




需求描述
需要單張圖片在可視區域內無縫持續向上滾動或向左滾動,由于向下和向右屬于反著坐標軸移動圖片,和正常DOM元素插入展示順序也相反,遂不考慮此種場景,
代碼實作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>滾動圖片</title> <style> /*豎向滾動*/ #container { width: 300px; height: 150px; overflow: hidden; margin: 100px; } #wrap { width: 100%; height: auto; display: flex; flex-direction: column; align-items: center; transform: translatez(0); } img { width: 100%; height: auto; } /*橫向滾動*/ /* #container { width: 300px; height: 150px; overflow: hidden; margin: 100px; } #wrap { width: auto; height: 100%; display: flex; flex-wrap: nowrap; align-items: center; transform: translatez(0); } img { width: auto; height: 100%; } */ </style> </head> <body> <div id="container"> <div id="wrap"> <!-- 橫圖 --> <!-- <img src="https://img1.baidu.com/it/u=49865366,3040475020&fm=253&fmt=auto&app=138&f=JPEG?w=751&h=500" alt="" /> --> <!-- 豎圖 --> <img src="https://img0.baidu.com/it/u=3724390669,1663648862&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=752" alt="" /> </div> </div> <script> // 功能:實作圖片無縫向上滾動 // run:運行圖片輪播 // pause:暫停圖片輪播 function imageScroll() { if ( /iP(ad|hone|od).*OS 13/.test(window.navigator.userAgent) || // iOS6 is buggy !window.requestAnimationFrame || !window.cancelAnimationFrame ) { let lastTime = 0; window.requestAnimationFrame = function (callback) { const now = Date.now(); const nextTime = Math.max(lastTime + 16, now); return setTimeout(function () { callback((lastTime = nextTime)); }, nextTime - now); }; window.cancelAnimationFrame = clearTimeout; } // 執行影片函式 const requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; // 取消執行影片函式 const cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame; // 初始化定義輪播函式 requestId = null; return function () { return { // imgWrap:圖片容器,放置多張圖片,整體進行滾動 // imgView: 圖片所展示區域的視窗view // step 每次移動的距離 // direction: 滾動方向,默認 "top" 持續向上滾動,可選值為 "top" 和 "left" run: (imgWrap, imgView, step = 1, direction = "top") => { if (!imgWrap || !imgView) { console.warn("請傳入引數形如[圖片包裹容器,圖片展示容器]"); return false; } // 獲取視窗寬度 const containerWidth = parseInt(imgView.clientWidth); // 獲取視窗高度 const containerHeight = parseInt(imgView.clientHeight); // 獲取圖片元素 const imgElem = imgWrap.querySelector("img"); // 獲取圖片寬度 const imgWidth = parseInt(imgElem.width); // 獲取圖片高度 const imgHeight = parseInt(imgElem.height); // 初始化移動距離 let distance = 0; // 定義 transform 值名稱 let transformV; // 初始化圖片移動置為0的邊界長度 let boundaryValue = 0; switch (direction) { case "left": // 向左滾動,值為 translateX transformV = "translateX"; // 置為 0 的邊界值為圖片寬度 boundaryValue = parseFloat(imgWidth); // 克隆的圖片個數,至少克隆一張 const num1 = Math.ceil(containerWidth / imgWidth) || 1; for (let index = 0; index < num1; index++) { // 克隆一張圖片并插入到圖片最后面 imgWrap.appendChild( imgWrap.querySelector("img").cloneNode(true) ); } break; default: // 向上滾動,值為 translateY transformV = "translateY"; // 置為 0 的邊界值為圖片高度 boundaryValue = parseFloat(imgHeight); // 克隆的圖片個數,至少克隆一張 const num2 = Math.ceil(containerHeight / imgHeight) || 1; for (let index = 0; index < num2; index++) { // 克隆一張圖片并插入到圖片最后面 imgWrap.appendChild( imgWrap.querySelector("img").cloneNode(true) ); } break; } // 定義滾動影片回呼函式 const scroll = () => { // 移動的距離=已經移動的距離+每步的長度 distance = distance + step; // 設定圖片容器的 transform imgWrap.style.transform = `${transformV}(-${distance}px)`; // 關鍵行:當移動距離大于邊界值時,重置 distance=0 if (distance >= boundaryValue) { distance = 0; } // 再次呼叫滾動影片 requestId = requestAnimationFrame(scroll); }; // 執行滾動影片,傳入滾動影片回呼函式 requestId = requestAnimationFrame(scroll); }, // 暫停影片 pause: () => { cancelAnimationFrame(requestId); }, }; }; } window.onload = () => { const scroll = imageScroll(); // 向左滾動 // scroll().run( // document.getElementById("wrap"), // document.getElementById("container"), // 0.5, // "left" // ); // 向上滾動 scroll().run( document.getElementById("wrap"), document.getElementById("container"), 1, "top" ); // 通過定時器可以實作圖片滾動幾秒后暫停,如下表示先滾動 4s 后暫停,之后每個隔 2s 再滾動,2秒后再暫停 // setInterval(() => { // scroll().pause(); // setTimeout(() => { // scroll().run( // document.getElementById("wrap"), // document.getElementById("container"), // 1, // "top" // ); // }, 2000); // }, 4000); }; </script> </body> </html>
備注
對于向上滾動和向左滾動兩種效果,css 樣式要同步修改,支持橫圖、豎圖滾動,
代碼中用到了百度圖片,侵刪,
參考鏈接
如何設計實作無縫輪播 【同時這里其他朋友答案也都很贊,收藏了】
requestAnimationFrame 知多少?【相關知識點與優勢可參考這里】
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/434438.html
標籤:JavaScript
上一篇:細聊正則運算式(附demo)
下一篇:Vuex的使用及map方法
