专栏首页前端与Java学习移动端轮播图笔记
原创

移动端轮播图笔记

1.触屏事件

1.1触屏事件概述

移动端浏览器兼容性好,我们不需要考虑以前JS的兼容问题,可以放心使用原生JS书写效果,但是移动端也有自己独特的地方,比如触屏事件touch(也叫触摸事件),Android和IOS都有。

touch对象代表一个触摸点,触摸点可能是一根手指,也可能是一根笔。触屏事件可以相应用户手指对屏幕或者触控板操作

常见的触屏事件:

  • 1.touchstart:手指触摸到一个DOM元素时触发
  • 2.touchmove:手指在一个DOM元素上滑动时触发
  • 3.touchend:手指从一个DOM元素上移开时触发

1.2触摸事件对象(TochEvent)

TouchEvent是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或者多个触点,使开发者可以检测触点的移动,触点的增加和减少,等等

touchstart、touchmove、touchend三个时间都会各自有事件对象

触摸事件对象终点我们看三个常见对象列表

  • 1.touches:正在触摸屏幕的所有手指的一个列表
  • 2.targetTouches:正在触摸当前DOM元素上的手指的一个列表(最常使用
  • 3.changeTouches:手指状态发生了改变的列表,从无到有,从有到无变化

1.3移动端拖动元素

1.touchstart、touchmove、touchend可以实现拖动元素

2.但是拖动元素需要当前手指的坐标值,我们可以使用targetTouches[0]里面的pageXpageY

3.移动端拖动的原理:手指移动中,计算出手指移动的距离。然后用盒子原来的位置+手指移动的距离

4.手指移动的距离:手指滑动中的位置减去手指刚开始触摸的位置

拖动元素三部曲:

(1)触摸元素touchstart:获取手指初始坐标,同时获得盒子原来的位置

(2)移动手指touchmove:计算手指的滑动距离,并且移动盒子

(3)离开手指touchend

注意:手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动e.preventDefault();

2.移动轮播案例

三张图片进行轮播,需要将第一张克隆一张到最后,最后一张克隆一张到第一张,大概意思为下图:

html布局

<div class="container">
        <div class="banner clearfix">
            <ul class="clearfix">
                <li><a href="#"><img src="images/ban3.jpg" alt=""></a></li>
                <li><a href="#"><img src="images/ban1.jpg" alt=""></a></li>
                <li><a href="#"><img src="images/ban2.jpg" alt=""></a></li>
                <li><a href="#"><img src="images/ban3.jpg" alt=""></a></li>
                <li><a href="#"><img src="images/ban1.jpg" alt=""></a></li>
            </ul>
            <!-- 小圆点 -->
            <ol>
                <li class="current"></li>
                <li></li>
                <li></li>
            </ol>
        </div>
</div>

css样式

    * {
            margin: 0px;
            padding: 0px;
            /* 移动端适配核心点
                1.不允许网页出现横向滚动条
                2.页面盛满屏幕,盒子宽度与屏幕一致 100%
                3.让盒子的内容宽高width/height包含padding与border,避免出现横向滚动条  
            */
            box-sizing: border-box;
        }
        body {
            /* 移动端默认字体一般是12px */
            font-size: 12px;
        }
        li {
            list-style: none;
        }
        img {
            vertical-align: middle;
            /* 图片居中 */
        }
        a {
            color: #000;
            /* 取消a标签默认下划线 */
            text-decoration: none;
            /* 移动端点击a链接出现蓝色背景问题解决 */
            -webkit-tap-highlight-color: transparent;
        }
        /* 清除浮动,解决margin-top塌陷 */
        .clearfix:after {
            content: "";
            display: block;
            height: 0;
            clear: both;
            visibility: hidden;
        }
        .container {
            width: 100%;
            /* 限制版心的宽度范围,在pc端也能显示移动端网页 */
            max-width: 1024px;
            min-width: 320px;
            margin: 0 auto;
        }
        .banner {
            width: 100%;
            margin-top: 44px;
            position: relative;
            overflow: hidden;
        }
        .banner img {
            width: 100%;
        }
        .banner ol {
            position: absolute;
            right: 20px;
            bottom: 5px;
        }
        .banner ol .current {
            width: 15px;
        }
        .banner ol li {
            display: inline-block;
            width: 5px;
            height: 5px;
            border-radius: 2px;
            list-style: none;
            background-color: red;
        }
        .banner ul {
            width: 500%;
            margin-left: -100%;
            overflow: hidden;
        }
        .banner ul li {
            float: left;
            width: 20%;
        }

案例分析:

  • 1.自动轮播
  • 2.开启定时器
  • 3.移动端移动,可以使用translate移动
  • 4.想要图片缓动效果,添加过渡transition效果

实现播放功能后,接着实现无缝滚动

  • 自动播放功能无缝滚动
  • 注意:我们判断条件是要等到图片滚动完毕再去判断,就是过渡完成后判断
  • 此时需要添加检测过渡完成事件transitionend
  • 判断条件:如果索引号等于3说明走到最后一张图片,此时索引号要复原为0
  • 此时图片,去掉过渡效果,然后移动
  • 如果索引号小于0,说明是倒着走,索引号改为2
  • 此时图片,去掉过渡效果,然后移动

无缝滚动实现完之后接着实现改变li小圆点的样式变换

这里介绍一个新的classList属性:它是HTML5新增的一个属性,返回元素的类名,但是ie10以上的版本才支持,该属性用于在元素中添加、移出、切换css类,有以下方法:

元素.classList.add('类名')、元素.classList.remove('类名')、元素.classList.toggle('类名')

    <style>
        .bg{
            background-color: black;
        }
    </style>
    
    <div class="one two"></div>
    <button>开关</button>
    <script>
        var div = document.querySelector("div");
        console.log(div.classList);//DOMTokenList(2) ["one", "two", value: "one two"]
        //1.添加类名 是在后面追加类名不会覆盖以前的类名
        div.classList.add('three');
        console.log(div.classList);//DOMTokenList(3) ["one", "two", "three", value: "one two three"]
        //2.删除类名
        div.classList.remove('one');
        console.log(div.classList);//DOMTokenList(2) ["two", "three", value: "two three"]
        //3.切换类
        var btn = document.querySelector("button");
        btn.onclick = function(){
            document.body.classList.toggle("bg");
        }
    </script>

了解完classList之后我们来做小圆点样式改变效果:

  • 1.小圆点跟随变化效果
  • 2.吧ol中li带有current类名选出来去掉类名current
  • 3.让当前索引号的li加上current
  • 4.注意:等着过渡结束之后再去添加current,所以要写在transitionend中

接着开始实现手指滑动轮播:

  • 1.本质就是ul跟着手指移动,简单说就是移动拖动元素
  • 2.触摸元素touchstart:获取手指初始坐标
  • 3.移动手指touchmove:计算手指的滑动距离,并且移动盒子
  • 4.手指离开touchend,根据移动距离去判断是回弹还是播放上一张下一张
  • 5.如果移动距离小于某个像素 就回弹
  • 6.如果移动距离大于某个像素就上一张或者下一张

js代码:

<script>
    //1.获取元素
    var banner = document.querySelector(".banner");
    var ul = document.querySelector(".banner ul");
    var ol = document.querySelector(".banner ol");
    //获取banner的宽度
    var w = banner.offsetWidth;
    //2.利用定时器自动轮播图片
    var index = 0;
    var timer = setInterval(function () {
        index++;
        var translatex = -index * w;
        ul.style.transition = "all .3s";
        ul.style.transform = "translateX(" + translatex + "px)";
    }, 2000);
    //等着过度完成之后,再去判断 监听过渡完成的时间transitionend
    ul.addEventListener("transitionend", function () {
        //无缝滚动
        if (index >= 3) {
            index = 0;
            //为了让图片瞬间到索引0处,要取消掉过渡效果
            ul.style.transition = "none";
            //利用最新的索引乘宽度 滚动图片
            var translatex = -index * w;
            ul.style.transform = "translateX(" + translatex + "px)";
        } else if (index < 0) { //同理
            index = 2;
            ul.style.transition = "none";
            var translatex = -index * w;
            ul.style.transform = "translateX(" + translatex + "px)";
        }
        //3.小圆点跟随变化
        //吧ol中的li带有current类名选出来去掉类名 remove
        ol.querySelector('.current').classList.remove('current')
        //让当前索引号的小li加上current 类名
        ol.children[index].classList.add('current');
    });

    //4.手指滑动轮播图
    //触摸元素touchstart:获取手指初始坐标
    var startX = 0;
    var moveX = 0; //因为后面需要使用移动距离,因此定义一个全局变量
    var flag = false;
    ul.addEventListener("touchstart", function (e) {
        //当触摸到ul时候 清除定时器
        clearInterval(timer);
        startX = e.targetTouches[0].pageX;
    });
    //移动手指 touchmove:计算手指的滑动距离 ,并且移动盒子
    ul.addEventListener("touchmove", function (e) {
        //计算移动距离
        moveX = e.targetTouches[0].pageX - startX;
        //移动盒子:盒子原来的位置+手指移动的距离
        var translateX = -index * w + moveX;
        //手指拖动的时候,不需要动画效果所以要取消过渡效果
        ul.style.transition = "none";
        ul.style.transform = "translateX(" + translateX + "px)";
        flag = true;//如果用户手指移动了我们才判断否则不去判断效果
        e.preventDefault();//阻止滚动屏幕的行为
    });
    //手指离开,根据移动距离去判断是回弹还是播放上一张下一张
    ul.addEventListener("touchend", function (e) {
        if (flag) {
            //如果移动距离大于50像素 我们就播放上一张或者下一张
            if (Math.abs(moveX) > 50) { //为了防止负数需要取绝对值
                //如果是右滑 播放上一张moveX是正数
                //如果是左滑 播放下一张moveX是负数
                moveX > 0 ? index-- : index++;

                var translateX = -index * w;
                ul.style.transition = "all .3s";
                ul.style.transform = "translateX(" + translateX + "px)";
            } else {
                //如果小于50px就回弹
                var translateX = -index * w;
                ul.style.transition = "all .1s";
                ul.style.transform = "translateX(" + translateX + "px)";
            }
        }
        //手指离开就清楚定时器
        clearInterval(timer);
        timer = setInterval(function () {
            index++;
            var translatex = -index * w;
            ul.style.transition = "all .3s";
            ul.style.transform = "translateX(" + translatex + "px)";
        }, 2000);
    });
</script>

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端移动web-day01学习笔记

    user-scalable=no:不允许手指缩放(因为一旦缩放就会出现水平滚动条)

    帅的一麻皮
  • ES6语法学习(变量的解构赋值)

    另一种情况是不完全解构:就是等号左边的模式只匹配一部分等号右边的数组,这样解构依然可以成功

    帅的一麻皮
  • 前端移动web-day04学习笔记

    优点 : 全适配 (一个HTML文件就可以适配所有的屏幕 )

    帅的一麻皮
  • 作为JavaScript的“超集”,感受一下TypeScript 的那些黑魔法

    TypeScript是一种由微软开发的、开源的编程语言,近两年发展迅猛,越来越多的JavaScript项目正在迁移到TypeScript,主流前端框架及Node...

    博文视点Broadview
  • 指北 | 谈谈ForkJoin框架的设计与实现

    相对于串行计算,并行计算可以划分成时间并行和空间并行。时间并行即指令流水化,也就是流水线技术。比如说生产一辆小汽车,有特定的轮子车间/发动机车间,同时进行各自的...

    猿天地
  • 瞎扯 Hbase ,很多人都理解错了

    今天扯一下 Hbase ,我对 Hbase 的了解起源于两篇文章Understanding HBase and BigTable和《李逵麻子,李鬼坑人--Big...

    哒呵呵
  • 使用FFmpeg库和API的介绍

    本文是来自SF Video Technology 2019年8月的演讲,演讲者是Matt Szatmary,演讲题目是"An Introduction to B...

    用户1324186
  • EOS被哄抢,不是没有理由的

    区块链大本营
  • Boost asio 心得笔记

    Boost asio中有两点用的不爽: 1. asio中的所有对象都引用io_service 2. async_write还要自己保证内存在completed之...

    知然
  • ES 深度分页scroll使用方式

    YG

扫码关注云+社区

领取腾讯云代金券