原生 js 实现移动端 Touch 轮播图

秒速五厘米 2022-03-30 20:39 323阅读 0赞

小编推荐:Fundebug专注于JavaScript、微信小程序、微信小游戏,Node.js和Java实时BUG监控。真的是一个很好用的bug监控费服务,众多大佬公司都在使用。

Touch 轮播图

touch轮播图其实就是通过手指的滑动,来左右切换轮播图,下面我们通过一个案例,来实现下。

1. html 结构

结构上,还是用 ulli来存放轮播图片, olli来存放轮播小圆点:

image

2. 样式初始化

html的一些标签,都会有一些默认样式,比如 body标签默认是有一个边距的,为了不影响美观,我们需要清除掉。

  1. /* 清除标签默认边距 */
  2. body,ul,li,ol,img {
  3. margin: 0;
  4. padding: 0;
  5. }
  6. /* 清除 ul 等标签前面的“小圆点” */
  7. ul,li,ol {
  8. list-style-type: none;
  9. }
  10. /* 图片自适应 */
  11. img {
  12. width: 100%;
  13. height: auto;
  14. border: none;
  15. /* ie8 */
  16. display: block;
  17. -ms-interpolation-mode: bicubic; /*为了照顾ie图片缩放失真*/
  18. }

image

3. 添加样式

在前面讲特效的时候,我们说过如何使用原生 js实现移一个轮播图的概念,但是当时的方式是通过 li浮动,这里给大家介绍一种新的方——定位。

思路:

  • ul外层的盒子一个相对定位;
  • 这里的ul高度不能写死,它应该是li撑开的高度,但是由于li绝对定位,没办法撑开这个高度,所以这里的ul需要在js里面动态设置高度;
  • li设置相对定位,并且lefttop都为0,再给li添加一个transform:translateX(300%)属性,目的是初始化显示的图片为空,然后在js里只需要动态设置每个litranslateX值,即可实现轮播;
  • 设置小圆点区域,因为小圆点个数未知,所以ol的宽度也未知,想要让一个未知宽度的盒子水平居中,可以使用absolute定位结合left百分比的方式实现;
  • ol下面的li设置一个宽高添加圆角边框属性,并且左浮动,这样就能显示一排空心的小圆点了;
  • 最后,添加一个样式类,里面设置一个背景属性,用来显示当前展示图片对应的小圆点。

    / 轮播图最外层盒子 /
    .carousel {

    1. position: relative;
    2. overflow: hidden;

    }

    .carousel ul {

    1. /* 这个高度需要在JS里面动态添加 */

    }

    .carousel ul li {

    1. position: absolute;
    2. width: 100%;
    3. left: 0;
    4. top: 0;
    5. /* 使用 transform:translaX(300%) 暂时将 li 移动到屏幕外面去*/
    6. -webkit-transform: translateX(300%);
    7. transform: translateX(300%);

    }

    / 小圆点盒子 /
    .carousel .points {

    1. /* 未知宽度的盒子,使用 absolute 定位,结合 transform 的方式进行居中 */
    2. position: absolute;
    3. left: 50%;
    4. bottom: 10px;
    5. transform: translateX(-50%);

    }

    / 小圆点 /
    .carousel .points li {

    1. width: 5px;
    2. height: 5px;
    3. border-radius: 50%;
    4. border: 1px solid #fff;
    5. float: left;
    6. margin: 0 2px;

    }

    / 选中小圆点的样式类 /
    .carousel .points li.active {

    1. background-color: #fff;

    }

image

4. js 准备工作

先不考虑别的, js在初始化的时候,首先要做的就是给 ul添加上一个高度,不然图片是不显示的。

  • UL动态设置高度
  • 动态生成小圆点 (根据图片的张数创建小圆点个数,i=0 添加active
  • 初始化三个li的基本位置

    • 定义三个变量,分别用来存储三个li的下(left存储最后一张图片的下标,centerright分别存储第一张和第二张的下标)
    • 通过数组[下标]的方式给三个li设置定位后left方向的位置

    var carousel = document.querySelector(‘.carousel’);
    var carouselUl = carousel.querySelector(‘ul’);
    var carouselLis = carouselUl.querySelectorAll(‘li’);
    var points = carousel.querySelector(‘ol’);
    // 屏幕的宽度(轮播图显示区域的宽度)
    var screenWidth = document.documentElement.offsetWidth;

    // 1- ul设置高度
    carouselUl.style.height = carouselLis[0].offsetHeight + ‘px’;

    // 2- 生成小圆点
    for(var i = 0; i < carouselLis.length; i++){

    1. var li = document.createElement('li');
    2. if(i == 0){
    3. li.classList.add('active');
    4. }//
    5. points.appendChild(li);

    }

    // 3- 初始三个 li 固定的位置
    var left = carouselLis.length - 1;
    var center = 0;
    var right = 1;

    // 归位
    carouselLis[left].style.transform = ‘translateX(‘+ (-screenWidth) +’px)’;
    carouselLis[center].style.transform = ‘translateX(0px)’;
    carouselLis[right].style.transform = ‘translateX(‘+ screenWidth +’px)’;

image

效果图:

image

5. 添加定时器,让图片动起来

轮播图都会自己轮播,所以需要用到定时器,每隔一段时间执行一次轮转函数。

  • 添加定时器,定时器里面轮转下标
  • 极值判断
  • 设置过渡(替补的那张不需要过渡)
  • 归位
  • 小圆点焦点联动

    var timer = null;
    // 调用定时器
    timer = setInterval(showNext, 2000);

    // 轮播图片切换
    function showNext(){

    1. // 轮转下标
    2. left = center;
    3. center = right;
    4. right++;
    5. // 极值判断
    6. if(right > carouselLis.length - 1){
    7. right = 0;
    8. }
    9. //添加过渡
    10. carouselLis[left].style.transition = 'transform 1s';
    11. carouselLis[center].style.transition = 'transform 1s';
    12. // 右边的图片永远是替补的,不能添加过渡
    13. carouselLis[right].style.transition = 'none';
    14. // 归位
    15. carouselLis[left].style.transform = 'translateX('+ (-screenWidth) +'px)';
    16. carouselLis[center].style.transform = 'translateX(0px)';
    17. carouselLis[right].style.transform = 'translateX('+ screenWidth +'px)';
    18. // 自动设置小圆点
    19. setPoint();

    }

    // 动态设置小圆点的active类
    var pointsLis = points.querySelectorAll(‘li’);
    function setPoint(){

    1. for(var i = 0; i < pointsLis.length; i++){
    2. pointsLis[i].classList.remove('active');
    3. }
    4. pointsLis[center].classList.add('active');

    }

image

效果图:

image

6. touch 滑动

移动端的轮播图,配合 touch滑动事件,效果更加友好。

  • 分别绑定三个touch事件

    • touchstart里面记录手指的位置,清除定时器,记录时间
    • touchmove里面获取差值,同时清除过渡,累加上差值的值
    • touchend里面判断是否滑动成功,滑动的依据是滑动的距离(绝对值)
  • 超过屏幕的三分之一或者滑动的时间小于300毫秒同时距离大于30(防止点击就跑)的时候都认为是滑动成功
  • 在滑动成功的条件分支里面在判断滑动的方向,根据方向选择调用上一张还是下一张的逻辑
  • 在滑动失败的条件分支里面添加上过渡,重新进行归位
  • 重启定时器

    var carousel = document.querySelector(‘.carousel’);
    var carouselUl = carousel.querySelector(‘ul’);
    var carouselLis = carouselUl.querySelectorAll(‘li’);
    var points = carousel.querySelector(‘ol’);
    // 屏幕的宽度
    var screenWidth = document.documentElement.offsetWidth;
    var timer = null;

    // 设置 ul 的高度
    carouselUl.style.height = carouselLis[0].offsetHeight + ‘px’;

    // 动态生成小圆点
    for (var i = 0; i < carouselLis.length; i++) {

    1. var li = document.createElement('li');
    2. if (i == 0) {
    3. li.classList.add('active');
    4. }
    5. points.appendChild(li);

    }

    // 初始三个固定的位置
    var left = carouselLis.length - 1;
    var center = 0;
    var right = 1;

    // 归位(多次使用,封装成函数)
    setTransform();

    // 调用定时器
    timer = setInterval(showNext, 2000);

    // 分别绑定touch事件
    var startX = 0; // 手指落点
    var startTime = null; // 开始触摸时间
    carouselUl.addEventListener(‘touchstart’, touchstartHandler); // 滑动开始绑定的函数 touchstartHandler
    carouselUl.addEventListener(‘touchmove’, touchmoveHandler); // 持续滑动绑定的函数 touchmoveHandler
    carouselUl.addEventListener(‘touchend’, touchendHandeler); // 滑动结束绑定的函数 touchendHandeler

    // 轮播图片切换下一张
    function showNext() {

    1. // 轮转下标
    2. left = center;
    3. center = right;
    4. right++;
    5. // 极值判断
    6. if (right > carouselLis.length - 1) {
    7. right = 0;
    8. }
    9. //添加过渡(多次使用,封装成函数)
    10. setTransition(1, 1, 0);
    11. // 归位
    12. setTransform();
    13. // 自动设置小圆点
    14. setPoint();

    }

    // 轮播图片切换上一张
    function showPrev() {

    1. // 轮转下标
    2. right = center;
    3. center = left;
    4. left--;
    5. // 极值判断
    6. if (left < 0) {
    7. left = carouselLis.length - 1;
    8. }
    9. //添加过渡
    10. setTransition(0, 1, 1);
    11. // 归位
    12. setTransform();
    13. // 自动设置小圆点
    14. setPoint();

    }

    // 滑动开始
    function touchstartHandler(e) {

    1. // 清除定时器
    2. clearInterval(timer);
    3. // 记录滑动开始的时间
    4. startTime = Date.now();
    5. // 记录手指最开始的落点
    6. startX = e.changedTouches[0].clientX;

    }
    // 滑动持续中
    function touchmoveHandler(e) {

    1. // 获取差值 自带正负
    2. var dx = e.changedTouches[0].clientX - startX;
    3. // 干掉过渡
    4. setTransition(0, 0, 0);
    5. // 归位
    6. setTransform(dx);

    }
    // 滑动结束
    function touchendHandeler(e) {

    1. // 在手指松开的时候,要判断当前是否滑动成功
    2. var dx = e.changedTouches[0].clientX - startX;
    3. // 获取时间差
    4. var dTime = Date.now() - startTime;
    5. // 滑动成功的依据是滑动的距离(绝对值)超过屏幕的三分之一 或者滑动的时间小于300毫秒同时滑动的距离大于30
    6. if (Math.abs(dx) > screenWidth / 3 || (dTime < 300 && Math.abs(dx) > 30)) {
    7. // 滑动成功了
    8. // 判断用户是往哪个方向滑
    9. if (dx > 0) {
    10. // 往右滑 看到上一张
    11. showPrev();
    12. } else {
    13. // 往左滑 看到下一张
    14. showNext();
    15. }
    16. } else {
    17. // 添加上过渡
    18. setTransition(1, 1, 1);
    19. // 滑动失败了
    20. setTransform();
    21. }
    22. // 重新启动定时器
    23. clearInterval(timer);
    24. // 调用定时器
    25. timer = setInterval(showNext, 2000);

    }
    // 设置过渡
    function setTransition(a, b, c) {

    1. if (a) {
    2. carouselLis[left].style.transition = 'transform 1s';
    3. } else {
    4. carouselLis[left].style.transition = 'none';
    5. }
    6. if (b) {
    7. carouselLis[center].style.transition = 'transform 1s';
    8. } else {
    9. carouselLis[center].style.transition = 'none';
    10. }
    11. if (c) {
    12. carouselLis[right].style.transition = 'transform 1s';
    13. } else {
    14. carouselLis[right].style.transition = 'none';
    15. }

    }

    // 封装归位
    function setTransform(dx) {

    1. dx = dx || 0;
    2. carouselLis[left].style.transform = 'translateX(' + (-screenWidth + dx) + 'px)';
    3. carouselLis[center].style.transform = 'translateX(' + dx + 'px)';
    4. carouselLis[right].style.transform = 'translateX(' + (screenWidth + dx) + 'px)';

    }
    // 动态设置小圆点的active类
    var pointsLis = points.querySelectorAll(‘li’);

    function setPoint() {

    1. for (var i = 0; i < pointsLis.length; i++) {
    2. pointsLis[i].classList.remove('active');
    3. }
    4. pointsLis[center].classList.add('active');

    }

image

效果图:

image

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了9亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

2018121912254161

发表评论

表情:
评论列表 (有 0 条评论,323人围观)

还没有评论,来说两句吧...

相关阅读

    相关 原生js实现

            很多很多网站经常会用到一个特效,那就是轮播图,对于日新月异的前端技术来说其实就是一个框架一个接口的事,但轮播的原理是什么?用最原始的javascript来写又是

    相关 原生js实现

    轮播图基本上是前端所必须面临的一个功能。而且在网上可以找到各种各样的插件或者写法。 但是我个人觉得还是写一下比较好。这里用到的是原生JS、CSS3相结合的写法。 对IE 8

    相关 原生js实现

    原生js实现轮播图  很多网站上都有轮播图,但却很难找到一个系统讲解的,因此这里做一个简单的介绍,希望大家都能有所收获,如果有哪些不正确的地方,希望大家可以指出。  [