強大的CSS:scroll-snap滾動事件停止及元素位置檢測
一、Scroll Snap是前端必備技能
CSS Scroll Snap是個非常好用的特性,可以讓網頁容器滾動停止的時候,無需任何JS程式碼的參與,瀏覽器可以自動平滑定位到指定元素的指定位置。類似幻燈片廣告效果就可以純CSS實現。
而且CSS Scroll Snap的相容性非常好,移動端幾乎可以放心使用。
二、源自實際專案的scroll-snap場景
今天下午在實現一個功能需求的時候,正好遇到一個場景非常適合使用Scroll Snap來實現,滑動依次顯示人物角色。於是就大膽使用了下,哇,好棒,無需任何js做邊界判斷,滑動停止自動定位到想要的位置。
關鍵CSS程式碼如下:
ul { width: 375px; height: 667px; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; white-space: nowrap; overflow-y: hidden; } li { display: inline-block; width: 100%; height: 100%; scroll-snap-align: center; }
滾動父容器元素設定
scroll-snap-type:x mandatory
,水平滾動,強制定位,子列表元素設定
scroll-snap-align:center
讓列表在滾動容器的中間顯示,於是效果達成。
然而,滾動定位結束後,還需要需要高亮當前定位的人物素材。我發現有些難辦了!
以前這種滑動效果用JS實現,無論是JS動畫結束,還是CSS動畫結束,都是有回撥函式可以使用的。但是這裡卻是滾動,而且滾動後還會自己再定位一會兒,自己定位時間有長有短,誰知道什麼時候停止?有時候一口氣滑多個元素,也不確定到底停止在哪個元素上。
實際上,標準制定者們和瀏覽器廠商正在積極推進Scroll Snap相關回撥事件的落地,這樣可以精確知道滾到什麼時候停止以及滾動定位到哪個元素上,但是,標準還在折騰,瀏覽器還沒有支援。專案現在就要用,怎麼辦呢?
對!肯定要出動JS輔助。
實際上,就算不是Scroll Snap的使用場景,就算是普通的滾動,由於滾動具有慣性,檢測滾動是否停止也是一個經常會遇到的需求。因此,有必要捋一個檢測滾動什麼時候停止的方法。
三、我的滾動中止檢測方法
檢測元素的滾動是否停止,我的實現思路是這樣的,在滾動事件中跑一個定時器,記錄當前時間的滾動距離和上一次滾動的距離是否相等,如果相等則認為滾動已經停止,如果不相等,則認為滾動依然在進行。
用JavaScript示意就是( 這個實現已作廢 ):
// 定時器,用來檢測水平滾動是否結束 var timer = null; // 上一次滾動的距離 var scrollLeft = 0, scrollTop = 0; // 滾動事件開始 container.addEventListener('scroll', function () { clearInterval(timer); // 重新新的定時器 timer = setInterval(function () { if (container.scrollLeft == scrollLeft && container.scrollTop == scrollTop) { // 滾動距離相等,認為停止滾動了 clearInterval(timer); // ... 做你想做的事情,如回撥處理 } else { // 否則,依然記住上一次滾動位置 scrollLeft = container.scrollLeft; scrollTop = container.scrollTop; } }, 100); });
如果你有興趣,可以對上面程式碼進行進一步封裝。
更新於翌日
滾動終止檢測可以無需判斷前後滾動距離是否相等,因為無論是慣性還是Snap定位scroll事件也是持續觸發的。因此,可以直接這樣:
// 定時器,用來檢測水平滾動是否結束 var timer = null; // 滾動事件開始 container.addEventListener('scroll', function () { clearTimeout(timer); // 重新新的定時器 timer = setTimeout(function () { // 無滾動事件觸發,認為停止滾動了 // ... 做你想做的事情,如回撥處理 }, 100); });
當然,上面提供的方法並不是非常精準的中止檢測,因為Scroll Snap最後的重定位瀏覽器自身有個檢測,這個檢測事件,根據我的反覆研究與測試,應該是
350ms
(實際執行可能會略微大幾毫秒),遠比上面設定的
100ms
要大,因此,會有一次錯誤的冗餘判斷,發生在Snap定位開始之前。
我想了想,這個問題無法避免,但也不是什麼大問題。總不可能設定
400ms
檢測,延遲太高,體驗不一定好。
四、當前滾動目標元素檢測方法
原理如下,遍歷所有的列表元素,檢測列表元素的左邊緣相對於滾動容器左邊緣(如果是左對齊-
scroll-snap-align:left
)或中心(居中對齊)或右邊緣(右對齊)的位置。當然,如果列表元素尺寸和滾動容器尺寸一致,則左中右邊緣檢測都可以。
JS示意:
[].slice.call(container.children).forEach(function (ele, index) { if (Math.abs(ele.getBoundingClientRect().left - container.getBoundingClientRect().left) < 10) { // 此刻的ele元素就是當前定位的元素 // ... 你可以對ele做你想做的事情 } else { // 此刻的ele元素不是當前定位的元素 } });
嚴格來講,應該計算是否等於
,而不是小於
10
,這裡嘛,加了點容錯區間吧。
搞定了上面2個需要JS輔助的需求點,最終的效果就出來了。
自己是一個五年的前端工程師,希望本文對你有幫助!
這裡推薦一下我的前端學習交流扣qun:731771211 ,裡面都是學習前端的,如果你想製作酷炫的網頁,想學習程式設計。自己整理了一份2019最全面前端學習資料,從最基礎的HTML+CSS+JS【炫酷特效,遊戲,外掛封裝,設計模式】到移動端HTML5的專案實戰的學習資料都有整理,送給每一位前端小夥伴,每天分享技術
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901074/viewspace-2645234/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- html/css 滾動到元素位置,顯示載入動畫HTMLCSS動畫
- 原生JS實現隨著滑鼠滾動到元素位置觸發對應css3動畫,簡單易用滾動監測JSCSSS3動畫
- 使用CSS隱藏元素滾動條CSS
- 檢視CentOS上Apache位置,版本,停止,啟動CentOSApache
- vue監聽頁面中的某個div的滾動事件,並判斷滾動的位置Vue事件
- RecyclerView滾動位置,滾動速度設定View
- 使用js控制滾動條的位置JS
- Android ScrollView滾動到指定View的位置AndroidView
- html元素滾動定位方法HTML
- css隱藏滾動條並可以滾動CSS
- 移動端點透事件--阻止滾動事件事件
- 強大的CSS動畫:Transition與AnimationCSS動畫
- [譯] 使用智慧 CSS 基於使用者滾動位置應用樣式CSS
- javaScript實現鍵盤控制元素移動位置及縮放JavaScript
- CSS滾動條美化CSS
- 最全的獲取元素寬高及位置的方法
- JavaScript 滾動條定位指定位置JavaScript
- JQuery4:滑鼠事件和滾動事件jQuery事件
- HTML表單元素及CSSHTMLCSS
- css隱藏滾動條CSS
- 谷歌工具檢視CSS程式碼定義的位置谷歌CSS
- react記錄頁面的滾動條位置React
- 1.21 JQuery4:滑鼠事件與滾動事件jQuery事件
- JavaScript滑鼠中鍵滾動事件JavaScript事件
- 強大的CSS:文字下波浪線動畫效果CSS動畫
- 直播平臺製作,禁止頁面滾動 / 滾動事件穿透事件穿透
- 獲取元素大小、偏移量及滑鼠位置
- 拖拽滾動檢視(一)
- css實現滾動輪播CSS
- CSS水平無縫滾動效果CSS
- CSS完成視差滾動效果CSS
- Vue 返回記住滾動條位置詳解Vue
- css實現隱藏滾動條並可以滾動內容CSS
- vue 監聽頁面滾動事件Vue事件
- win10系統如何停止強制自動更新_win10停止強制自動更新的方法Win10
- angular 監聽 Windows 滾動事件 實現頁面滾動載入AngularWindows事件
- 基於ARkit和SceneKit檢測相機位置和設定2個物體碰撞的事件事件
- JavaScript的基礎語法及DOM元素和事件JavaScript事件