还在为无缝滚动而烦恼?是时候彻底get到这个知识点了_html/css_WEB-ITnose
最近一直在忙公司炒股大赛的页面,终于在昨天把他给上线了。一个看似简单的页面,做起来才知道其中的艰辛,暗藏深坑。由于直接使用jquery来写页面逻辑,因此要比想象中复杂很多。无论是从布局,功能还是逻辑上来说,都有值得总结的地方。
点击可查看我昨天上线的页面
这篇文章主要说说关于无缝滚动的实现。
刚开始学习js的时候,真心觉得无缝滚动是一个神奇的功能。背后到底是怎么回事?为什么明明只有几个方块就是滚不到头?后来明白了原理之后,发现原来是通过一些障眼法来实现。
原理
假如需要无缝滚动的4个元素是一个 ul.items中的6个 li.item。我们将控制 ul.items在容器 .wrap中滚动。html代码如下:
ul.items表示className为items的ul元素,其他地方同理
<div class="wrap"> <ul class="items"><!-- --><li class="item"><img src="/static/imghw/default1.png" data-src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner0.8a07a886.jpg" class="lazy" alt=""></li><!-- --><li class="item"><img src="/static/imghw/default1.png" data-src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner1.56bcecb3.png" class="lazy" alt=""></li><!-- --><li class="item"><img src="/static/imghw/default1.png" data-src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner2.9a7e8842.jpg" class="lazy" alt=""></li><!-- --><li class="item"><img src="/static/imghw/default1.png" data-src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner3.47acdfbd.png" class="lazy" alt=""></li><!-- --><li class="item"><img src="/static/imghw/default1.png" data-src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner5.e9205d49.jpg" class="lazy" alt=""></li><!-- --><li class="item"><img src="/static/imghw/default1.png" data-src="https://static.tigerbrokers.com/portal/images/cooperation/stockGame/v2-partner6.83b14a71.png" class="lazy" alt=""></li><!-- --></ul></div>
我们的目标是实现水平方向上的滚动,因此需要 li.item水平排列。能够达到目标的方式常用的有使用 float: left,或者使用 display: inline-block。我们知道控制页面元素的移动无非就是控制元素的 left, top, translateX, translateY,还有一种就是控制滚动距离 scrollTop, scrollLeft。布局的选择,同时也会影响到js控制属性的选择。
本例选择使用 display: inline-block布局,并控制 ul.items的 scrollLeft值,让整个ul滚动起来。布局上需要注意的有以下几点:
-
超出容器的部分需要隐藏,注意,此处的隐藏是给 ul.items的,注意与 float: left布局的差别。
.items { overflow: hidden; }
登录后复制 -
ul.items的内容不能折行,因此
.items { white-space: nowrap; }
登录后复制 -
需要适配到移动端,因此 li.item的宽度就必然会随着设配宽度的变小而变小。
@media (max-width: 780px) { .item { width: 190px; }}@media (max-width: 580px) { .item { width: 160px; }}
登录后复制 -
html布局中的 是为了消除 display: inline-block元素之间带来的间隙。
那么无缝滚动的障眼法到底是什么呢?本来用图片描述会更加直观一点,不过这里我想偷个懒,用文字给大家讲述一下,希望大家能看懂。
我们有子元素123456, 一个一个向左滚动,复制一份,就变成 123456123456。如果我们在整体移动到第二个1的时候,将整体的位置拉回到第一个1来,也就是初始位置,由于有 div.items的 overflow: hidden在,中间发生的变化我们没办法用肉眼识别出来,就感觉是一直在向左移动,永远都停不下来。
表达能力有限,如果没懂再结合代码理解一下吧,或者留言给我
功能实现
一说到运动,我们常常想到的方法可能是利用 setTimeout或者 setInterval, 不过呢,html5为我们提供了一个更加高性能的方法 requestAnimationFrame。
在性能上, requestAnimationFrame > setTimeout > setInterval。具体原因大家可以找找相关的资料了解一下。而 setTimeout的最小定时值为 100/60,因此,我们在实现运动时,从性能与兼容性两方面考虑,常常会如下声明:
var lastTime = 0, nextFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) { var currTime = + new Date, delay = Math.max(1000/60, 1000/60 - (currTime - lastTime)); lastTime = currTime + delay; return setTimeout(callback, delay); }, cancelFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || clearTimeout;
我们需要知道滚动到什么位置回退到0,这个位置刚好就是复制之前所有子元素加一起的总长度。但是子元素的宽度会因为设备宽度的改变而改变,因此配合布局,我们需要作如下处理:
// 单个子元素的宽度var itemW = 240;if ($items.children().eq(0).width() == 190) { itemW = 190;}if ($items.children().eq(0).width() == 160) { itemW = 160;}// 目标位置var target = itemW * $items.children().length;
为了实现障眼法,需要复制一份子元素
$items.html( $items.html() + $items.html() );
定义一个运动函数,这里的运动为匀速运动,因此比较简单,只需要一直+1即可。如果需要运动快一点,就多加一点
var timer = null;function adAni() { timer = nextFrame(function() { scrollX += 1; // 当递增到大于了目标距离,就直接变为0 if (scrollX >= target) { scrollX = 0; } $items.scrollLeft(scrollX); adAni(); });}// 运行这个函数就可以实现无缝滚动啦。adAni();
这样无缝滚动就已经实现了。不过还有一些其他的需求。比如,鼠标mouseover时,需要停止滚动,离开之后又要重新启动滚动。因为需求的变化,在移动端还需要能够滑动 items.ul,手指松开之后继续滚动。因此我们需要一个区别pc于移动端的函数。通过UA的不同来区分。
function isMobile() { return /(iphone|ipad|ipod|ios|android|mobile|blackberry|iemobile|mqqbrowser|juc|fennec|wosbrowser|browserng|Webos|symbian|windows phone)/i.test(navigator.userAgent);}
在pc端,鼠标移入时停止,鼠标移除时继续滚动
if (!isMobile()) { $items.on('mouseover', function() { cancelFrame(timer); }).on('mouseout', function() { adAni(); });}
在移动端,可以左右滑动,滑动时停止自动滚动,松开之后继续自动滚动。移动端的滑动事件,主要通过 touchstart, touchmove, touchend来实现,与pc端的 mousedown, mousemove, mouseup类似。
var sX, sL;$items.on('touchstart', function(e) { cancelFrame(timer); sX = e.originalEvent.changedTouches[0].pageX; sL = $items.scrollLeft();}).on('touchmove', function(e) { var dis = e.originalEvent.changedTouches[0].pageX - sX; var nowX = sL - dis; if (nowX > target) { nowX = 0; } $items.scrollLeft(nowX);}).on('touchend', function(e) { scrollX = $items.scrollLeft(); if (scrollX >= target) { scrollX = 0; } adAni();})
那么到这里,就已经基本搞定啦。虽然是一个比较简单的小例子,但是其中也包含了一些常用的功能,比如使用 requestAnimationFrame来实现运动,移动端的滑动事件等。在这里总结一下分享给大家,有疑问欢迎探讨。
由于segmentfault的文章中不支持codepen的demo,因此大家可以到文初提供的链接查看,也可以到我的个人博客里面查看 博客原文。
如果大家有任何疑问,都可以在公众号里面留言给我,微信中搜索 isreact可以找到我^_^,我需要您的关注。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

本文讨论了HTML&lt; Progress&gt;元素,其目的,样式和与&lt; meter&gt;元素。主要重点是使用&lt; progress&gt;为了完成任务和LT;仪表&gt;对于stati

本文讨论了html&lt; datalist&gt;元素,通过提供自动完整建议,改善用户体验并减少错误来增强表格。Character计数:159

本文讨论了HTML&lt; meter&gt;元素,用于在一个范围内显示标量或分数值及其在Web开发中的常见应用。它区分了&lt; meter&gt;从&lt; progress&gt;和前

本文解释了HTML5&lt; time&gt;语义日期/时间表示的元素。 它强调了DateTime属性对机器可读性(ISO 8601格式)的重要性,并在人类可读文本旁边,增强Accessibilit

本文讨论了使用HTML5表单验证属性,例如必需的,图案,最小,最大和长度限制,以直接在浏览器中验证用户输入。

本文讨论了视口元标签,这对于移动设备上的响应式Web设计至关重要。它解释了如何正确使用确保最佳的内容缩放和用户交互,而滥用可能会导致设计和可访问性问题。

本文讨论了&lt; iframe&gt;将外部内容嵌入网页,其常见用途,安全风险以及诸如对象标签和API等替代方案的目的。
