목차
原理
功能实现
웹 프론트엔드 HTML 튜토리얼 还在为无缝滚动而烦恼?是时候彻底get到这个知识点了_html/css_WEB-ITnose

还在为无缝滚动而烦恼?是时候彻底get到这个知识点了_html/css_WEB-ITnose

Jun 21, 2016 am 08:48 AM

最近一直在忙公司炒股大赛的页面,终于在昨天把他给上线了。一个看似简单的页面,做起来才知道其中的艰辛,暗藏深坑。由于直接使用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滚动起来。布局上需要注意的有以下几点:

  1. 超出容器的部分需要隐藏,注意,此处的隐藏是给 ul.items的,注意与 float: left布局的差别。

    .items { overflow: hidden; }
    로그인 후 복사
  2. ul.items的内容不能折行,因此

    .items { white-space: nowrap; }
    로그인 후 복사
  3. 需要适配到移动端,因此 li.item的宽度就必然会随着设配宽度的变小而变小。

    @media (max-width: 780px) {    .item {        width: 190px;    }}@media (max-width: 580px) {    .item {        width: 160px;    }}
    로그인 후 복사
  4. 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可以找到我^_^,我需要您的关注。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

& lt; Progress & Gt의 목적은 무엇입니까? 요소? & lt; Progress & Gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:34 PM

이 기사는 HTML & lt; Progress & Gt에 대해 설명합니다. 요소, 그 목적, 스타일 및 & lt; meter & gt의 차이; 요소. 주요 초점은 & lt; progress & gt; 작업 완료 및 & lt; meter & gt; Stati의 경우

& lt; datalist & gt의 목적은 무엇입니까? 요소? & lt; datalist & gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:33 PM

이 기사는 HTML & LT; Datalist & GT에 대해 논의합니다. 자동 완성 제안을 제공하고, 사용자 경험을 향상시키고, 오류를 줄임으로써 양식을 향상시키는 요소. 문자 수 : 159

HTML5의 크로스 브라우저 호환성에 대한 모범 사례는 무엇입니까? HTML5의 크로스 브라우저 호환성에 대한 모범 사례는 무엇입니까? Mar 17, 2025 pm 12:20 PM

기사는 HTML5 크로스 브라우저 호환성을 보장하기위한 모범 사례에 대해 논의하고 기능 감지, 점진적 향상 및 테스트 방법에 중점을 둡니다.

& lt; meter & gt의 목적은 무엇입니까? 요소? & lt; meter & gt의 목적은 무엇입니까? 요소? Mar 21, 2025 pm 12:35 PM

이 기사는 HTML & lt; meter & gt에 대해 설명합니다. 범위 내에 스칼라 또는 분수 값을 표시하는 데 사용되는 요소 및 웹 개발의 일반적인 응용 프로그램. & lt; meter & gt; & lt; Progress & Gt; 그리고 Ex

html5 & lt; time & gt; 의미 적으로 날짜와 시간을 나타내는 요소? html5 & lt; time & gt; 의미 적으로 날짜와 시간을 나타내는 요소? Mar 12, 2025 pm 04:05 PM

이 기사는 html5 & lt; time & gt; 시맨틱 날짜/시간 표현 요소. 인간이 읽을 수있는 텍스트와 함께 기계 가독성 (ISO 8601 형식)에 대한 DateTime 속성의 중요성을 강조하여 Accessibilit를 향상시킵니다.

HTML5 양식 유효성 검사 속성을 사용하여 사용자 입력을 유효성있게하려면 어떻게합니까? HTML5 양식 유효성 검사 속성을 사용하여 사용자 입력을 유효성있게하려면 어떻게합니까? Mar 17, 2025 pm 12:27 PM

이 기사에서는 브라우저에서 직접 사용자 입력을 검증하기 위해 필요한, Pattern, Min, Max 및 Length 한계와 같은 HTML5 양식 검증 속성을 사용하는 것에 대해 설명합니다.

뷰포트 메타 태그는 무엇입니까? 반응 형 디자인에 중요한 이유는 무엇입니까? 뷰포트 메타 태그는 무엇입니까? 반응 형 디자인에 중요한 이유는 무엇입니까? Mar 20, 2025 pm 05:56 PM

이 기사는 모바일 장치의 반응 형 웹 디자인에 필수적인 Viewport Meta Tag에 대해 설명합니다. 적절한 사용이 최적의 컨텐츠 스케일링 및 사용자 상호 작용을 보장하는 방법을 설명하는 반면, 오용은 설계 및 접근성 문제로 이어질 수 있습니다.

& lt; iframe & gt; 꼬리표? 보안을 사용할 때 보안 고려 사항은 무엇입니까? & lt; iframe & gt; 꼬리표? 보안을 사용할 때 보안 고려 사항은 무엇입니까? Mar 20, 2025 pm 06:05 PM

이 기사는 & lt; iframe & gt; 외부 컨텐츠를 웹 페이지, 공통 용도, 보안 위험 및 객체 태그 및 API와 같은 대안을 포함시키는 태그의 목적.

See all articles