JS进阶篇:移动端常用特效

移动端网页特效

一、触屏事件

1.1概述

移动端的兼容性极佳,无需考虑js的兼容问题,而移动端的独特事件---touch事件(也称为触摸事件),Android和js都有。

touch对象代表一个触摸点,可为手指/触控笔。该事件可响应用户手指对屏幕(或触控板)操作。

  • 常见触屏事件:

1679795354059

1.2touchstart事件

手指触碰到DOM元素时触发

<div></div>
<script>
div.addEventListener('touchstart',function(){
   //执行语句;
})
</script>

1.3touchmove事件

手指按住DOM元素移动时触发

<div></div>
<script>
var div = document.querySelector('div');
div.addEventListener('touchmove',function(){
   //执行事件
})
</script>

1.4touchend事件

手指摸完离开DOM元素时触发

<div></div>
<script>
var div = document.querySelector('div');
div.addEventListener('touchend',function(){
   //执行事件
})
</script>

1.5触摸事件对象 TouchEvent

TouchEvent是用来描述手指在触摸平面的状态变化的事件。用于描述一个/多个触点

【同鼠标事件对象mouseEvent】

  • 如:

    触点移动、触点增加和减少等

touchstart、touchmove、touchend都各自有事件对象

  • 常见的对象列表:

1679801150726

1.5.1e.touches

获取正在触摸的所有手指点的数量

  • 列表形式,可通过length获得列表长度=几个手指
1.5.2e.targetTouches

获取正在触摸当前DOM元素上的手指列表

  • 如果侦听的是一个DOM元素,而非document,那么touches和targetTouches获取的是一样的。

要获取第几个手指的相关信息,如:手指坐标,状态等

  • 可利用e.targetTouches[下标]得到

1679801706338

1.5.3e.changeTouches

获取手指状态改变的列表

  • 从无到有、从有到无
  • 手指离开时,仍可获得changeTouches列表

1.6移动端拖动元素

要实现拖动元素,将拖动时手指的x,y坐标赋给盒子即可

①touchstart、touchmove、touchend可实现拖动元素

②但拖动元素需要获取手指的坐标,利用targetTouches[下标]里面的pageX和pageY

③原理:计算手指移动距离,再把它赋给盒子实现拖动效果

  • 原来盒子的坐标位置+手指移动的距离=最终距离
    • 手指移动的距离:手指滑动中的位置-手指刚开始触摸的位置
    • 盒子坐标距离 element.offset
代码思路

(1)定义全局变量

  • 手指初始位置:startX、startY
  • 盒子初始位置:x、y

(2)触摸元素touchstart: 获取手指初始坐标,同时获得盒子移动前位置

  • 手指初始坐标:
    • startX=e.targetTouches[0].pageX
    • startY=e.targetTouches[0].pageY
  • 盒子移动前坐标:
    • x = this.offsetLeft
    • y = this.offsetTop
    • this表示绑定的事件对象,即touchstart事件对象--div

(3)移x动手指 touchmove:计算手指移动距离,并移动盒子

  • 手指移动距离:当前手指坐标-手指初始坐标
    • moveX = e.targetTouches[0].offsetLeft - startX;
    • moveY = e.targetTouches[0].offsetTop - startY;
  • 移动盒子:手指移动距离+盒子初始坐标+'px'
    • this.style.offsetLeft = x + moveX + 'px';
    • this.style.offsetTop = y + moveY + 'px';

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

❗:移动的盒子必须设置绝对定位,否则无法移动

html+css代码
<style>
div{
    position: absolute;
    left: 0;
   background-color: aqua;
   width: 200px;
   height: 200px;
}
</style>
<body>
    <div></div>
js代码
  <script>
        //(1)获取盒子元素
        var div = document.querySelector('div');
        //(2)盒子运动前位置
        var x = 0;
        var y = 0;
        //(3)手指的初始位置
        var startX = 0;
        var startY = 0; 
        //(4)在手指第一次点击时,获得①手指的初始位置+②盒子移动前的位置
        div.addEventListener('touchstart',function(e){
            startX = e.targetTouches[0].pageX;
            startY = e.targetTouches[0].pageY;
            x = this.offsetLeft;
            y = this.offsetTop;
            console.log(x);
            console.log(y);
        });
        //(5)手指移动时,获取①手指移动的位置:当前手指位置-初始手指位置
        //②盒子移动位置:手指移动位置+盒子初始位置,赋给盒子
        div.addEventListener('touchmove',function(e){
            //计算手指移动距离:目前手指位置-手指初始位置
            var moveX = e.targetTouches[0].pageX - startX;
            var moveY = e.targetTouches[0].pageY - startY;
            //移动盒子:盒子初始位置+手指移动位置
            this.style.left = x + moveX + 'px';
            this.style.top = y + moveY + 'px';
            
            console.log(this.style.left);
            console.log(this.style.top);
            e.preventDefault();//放置手指滑动的屏幕滚动行为
        });

    </script>

二、移动端常见特效

2.1classList属性

classList属性是HTML5新增的属性,用于返回元素的所有类名列表【ie10以上版本支持】

  • 还可用于添加、移除和切换CSS类

(1)添加类

  • 直接写类名,即可
element.classList.add(‘类名’)

(2)删除类

element.classList.remove('类名')

(3)切换类

  • 有该类,就加上
  • 没有该类,就去除
element.classList.toggle('类名')

(4)好处

相比于之前的className,它不会覆盖原先的class,而是在后面追加。

2.2轮播图

1️⃣都可以自动播放图片

2️⃣手指可以拖动播放轮播图

1679842351648

静态页面:

轮播图最前方,加上3

轮播图最后方,加上1

  • ul轮播区域,li放img ,同时设置浮动;

  • ul宽度设置为500%放五张照片

  • li宽度设置为20%,使其放入u

  • 要让用户看到1,而非加的3,修改margin-left为-100%

js思路:

1️⃣自动播放效果

①利用定时器,使轮播图自动播放

  • 定义变量,每次++,移动距离=变量*图片宽度

  • transform移动 element.style.transform = 'translateX ( 移动的像素 px)'

    1679845156358

②因为使用到过渡效果,所以利用transitionend事件,检测过渡事件是否完成,完成后再去判断,使图片跳转回第一张。

  • 利用index变量,侦听transitionend事件

  • 【正着走】if index>=3 令 index = 0 跳到第一张图

    • 去除过渡 ul.style.transition = 'none'

    • translateX = -index * w

    • 移动 ul.style.transform = 'translateX('+translateX+'px)'

      1679846637765

  • 【倒着走】if index <0 令 index=2跳到最后一张图

    • 去除过渡ul.style.transition = 'none'快速到最后一张
    • translateX = -index *w
    • 移动ul.style.transform = 'translateX('+translateX+'px)'

1679846701481

2️⃣下方小圆点随图片切换

主要利用classList属性

①把ol中li带有current类名全选出来,去除类名

  • element.classList.remove('current')

②再让当前索引号的li加上current类

  • element.classList.add('current')

1679847763387

3️⃣手指拖动轮播图

本质就是ul跟着手指动

①touchstart触摸手指,获取手指初始坐标

  • 停止定时器,轮播图停止自动播放

1680019968711

②touchmove移动手指

  • 计算手指移动距离:当前坐标-初始坐标
  • 移动盒子:盒子原先位置+手指移动距离+'px'
  • 清除过渡效果
  • transform移动

1680010071197

③touchend松开手指

  • 根据移动距离决定,向左回弹,还是向右回弹

    • 移动距离大于某像素,就播放上一张、下一张滑动

      • 注意取绝对值 Math.abs,因为可能左滑/右滑
      • 移动距离为正:表示右滑--》播放上一张
      • 移动距离为负:表示左滑--》播放下一张

        1680020670214

    • 移动距离小于某像素,回弹至原来位置

      1680020846430

  • 手指离开再重新开启定时器,让轮播图自动播放

    • 先清除,保证只有一个定时器
    • 再开启,复制第一次开启的代码即可

    1680021075606

1680020228962

4️⃣优化

①鼠标点击不拖动,不进行判断滚动上一张/下一张

  • 定义全局变量flag,初值为flase,touchmove鼠标移动中变为true

②手指移动轮播图,阻止屏幕滚动行为

  • touchmove事件中,添加e.preventDefault()
完整代码
(1)html部分
 <!-- 焦点图模块 -->

    <div class="focus">

        <ul>

            <!-- 将图片3复制一份到图片1的前面 -->

            <!-- 为了使得手指移动图片1的时候,前面不会有空白 -->

            <li><img src="upload/focus3.jpg" alt=""></li>

            <li><img src="upload/focus1.jpg" alt=""></li>

            <li><img src="upload/focus2.jpg" alt=""></li>

            <li><img src="upload/focus3.jpg" alt=""></li>

            <!-- 复制图片1到图片3的最后 -->

            <li><img src="upload/focus1.jpg" alt=""></li>

        </ul>

        <ol>

            <li class="current"></li>

            <li></li>

            <li></li>

        </ol>

    </div>
(2)css部分
/* focus */
.focus {

    position: relative;

    padding-top: 44px;

    overflow: hidden;

}

.focus img {

    width: 100%;

}

.focus ul {

    width: 500%;

    margin-left: -100%;

}

.focus ul li {

    float: left;

    width: 20%;

}

.focus ol {

    position: absolute;

    bottom: -9px;

    right: 5px;

}

.focus ol li {

    display: inline-block;

    width: 5px;

    height: 5px;

    background-color: #fff;

    list-style: none;

    border-radius: 2px;

    /* 给ol里的li也就是小圆点加transition过渡,让小圆点的变化更自然 */

    transition: all .3s;

}

.focus ol li.current {

    width: 15px;

}
(3)js部分
window.addEventListener('load', function () {//等整个页面加载完毕,再运用js
    // 1.获取元素
    var focus = document.querySelector('.focus');
    var ul = focus.children[0];
    var ol = focus.children[1];
    // 移动的每张图片的宽度,就是focus宽度
    // 获得focus的宽度
    var w = focus.offsetWidth;
    // 2.利用定时器自动轮播图片
    // 声明一个变量index来控制ul每次移动
    var index = 0;
    var timer = setInterval(function () {
        index++;
        var translatex = -index * w;//因为是往左走,所以是负值
        ul.style.transition = 'all .3s';//添加过渡,让图片慢点自动滚动
        ul.style.transform = 'translateX(' + translatex + 'px)';//每隔2S,往左滚动一张图片
    }, 2000);
    // 等着过渡完成之后,再去判断 监听过渡完成的事件 transitionend 
    ul.addEventListener('transitionend', function () {
        // 无缝滚动
        // 第一个focus1的index是0,最后一个focus1的index是3
        // 当index变为3或更大的时候,跳转回index为0
        if (index >= 3) {
            index = 0;
            // 去掉过渡,直接跳转
            ul.style.transition = 'none';
            // 用最新的index*宽度,继续滚动图片
            var translatex = -index * w;
            ul.style.transform = 'translateX(' + translatex + 'px)';
        } else if (index < 0) {
            // 当index<0的时候,跳转回index为2
            index = 2;
            // 去掉过渡,直接跳转
            ul.style.transition = 'none';
            // 用最新的index*宽度,继续滚动图片
            var translatex = -index * w;
            ul.style.transform = 'translateX(' + translatex + 'px)';
        }
        // 3.小圆点跟随变化效果
        // 移除(classList.remove)ol中li中有current类名的li
        ol.querySelector('li.current').classList.remove('current');
        // 给当前index的li添加(classList.add)类名current
        ol.children[index].classList.add('current');
 
    });
    // 4.手指滑动轮播图
    // 本质上是让ul跟随手指移动
    // 触摸元素(touchstart)获得手指初始坐标
    // 此处是左右滑动,所以只需要X坐标
    var startX = 0;
    var moveX = 0;//之后会使用到该移动距离,所以要是全局变量
    var flag = false;//声明一个全局变量flag
    ul.addEventListener('touchstart', function (e) {
        startX = e.targetTouches[0].pageX;
        // 手指滑动轮播图的时候,要停止轮播图的自动滚动
        // 当手指按下时候,就停止图片自动滚动
        clearInterval(timer);
    });
 
    // 手指滑动(touchmove)获得手指移动距离
    ul.addEventListener('touchmove', function (e) {
        // 手指移动距离=手指滑动时的手指X坐标-手指初始X坐标
        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的时候,让屏幕滚动的行为
    });
    // 手指移开(touchend)根据移动距离判断是 回弹 还是 播放上一张/下一张
    ul.addEventListener('touchend', function (e) {
        if (flag) {//如果用户手指移动过再去判断,不然不判断
            // (1)如果移动距离大于50px,则播放上一张/下一张
            if (Math.abs(moveX) > 50) {
                // 如果是右滑,则播放下一张,moveX是正值
                if (moveX > 0) {
                    index--;
                } else {
                    // 如果是左滑,则播放上一张,moveX是负值
                    index++;
                }
                // 用最新的index*宽度,继续滚动图片
                var translatex = -index * w;
                // 图片滚动时要有过渡效果
                ul.style.transition = 'all .3s';
                ul.style.transform = 'translateX(' + translatex + 'px)';
            } else {
                // (2)如果移动距离小于50px,则回弹
                // 用最新的index*宽度,继续滚动图片
                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);
    });
})

2.3返回顶部

滚动到某个地方,显示[返回顶部],否则隐藏

①滚动到某位置,显示[返回顶部]

  • 绑定scroll滚动事件

  • 滚动某位置:window.pageY = ?,

    • ?表示滚动到某盒子处,可用element.offsetTop获取
  • 显示:element.style.display = 'block'

②点击[返回顶部],回到页面顶部

  • 利用window.scroll(0,0)返回顶部

(1)html代码

  <div class="goBack">返回顶部</div>

(2)css代码

    body{
        height: 3000px;
    }
    .goBack{
        position:fixed;
        bottom:50px;
        right: 20px;
        width: 38px;
        height: 38px;
        background: url(./img/cloud.png) no-repeat;
        /* 一开始不显示,移动到某位置显示 */
        display: none;
    }

(3)js代码

        var goBack = document.querySelector('.goBack');
         //(1)滑动到某位置,显示返回顶部
        document.addEventListener('scroll',function(){
            if(window.pageYOffset >= 100){
               goBack.style.display = 'block';
            }else{
               goBack.style.display = 'none';
            }
       });
       //(2)点击返回顶部,跳转页面上方
       document.addEventListener('click',function(){
          window.scroll(0,0)
       })

2.4click延时解决方案

移动端中的click事件有300ms的延时,原因是缩放页面,常使用双击复原缩放页面。

  • 因而移动端每次就会等待300ms,防止有下一次的点击

若要使得点击后,不进行延迟等待,解决方案如下:

(1)禁用缩放

禁用浏览器默认双击缩放行为并去除300ms的点击延迟

  • html头部添加 content="user-scalable=no"
<meta name="viewport" content="user-scalable=no">
(2)封装事件

利用touch事件自己封装这个事件解决300ms延迟

  • 原理:

    • 当手指触摸屏幕,记录当前触摸时间
    • 当手指离开屏幕,用离开时间-触摸时间
    • 若<150ms,且未滑动过屏幕,定义为点击
    • 若<150ms,但滑动过屏幕,不定义为点击

    1680057827519

(3)fastclick插件

若页面需要缩放效果,第一种✖

若有多个元素需解决延迟,第二种✖

fastclick插件是解决 300ms延迟的js文件

①下载js文件

下载地址:https://github.com/ftlabs/fastclick

1680058585540

②将fastclick.js引入要使用的html页面中

官方上复制,太长了在此不赘述

③按照语法规范,添加js代码

if ('addEventListener' in document) {
	document.addEventListener('DOMContentLoaded', function() {
		FastClick.attach(document.body);
	}, false);
}

④至此,该页面中所有click延迟问题都被解决了

三、移动常用开发插件

3.1什么是插件?

js插件是js文件,遵循一定规范编写,方便展示和调用。

  • 如:轮播图、瀑布流插件
  • 特点:解决某问题而存在,功能单一且小

3.2插件的使用

在github仓库:https://github.com中下载时,都有官方使用说明

(1)下载/拷贝插件

(2)按照文档使用说明

1680059069363

  • 寻找想要的demo效果
  • 引入css,js文件
  • 复制html代码结构

(3)按照官方API说明,修改效果

(4)完成自己页面的代码编写 end

3.3Swiper插件

Swiper插件用于轮播图

中文官网地址https://www.swiper.com.cn

(1)官网下载Swiper

打开官网->点击获取Swiper-》选择下载Swiper

1680059489164

点击下载Swiper版本

1680059598190

1680059611573

(2)引入插件相关文件

解压缩后,demo存放所有示例的html文件

1680059832191

编号对应官网的演示编号

1680059890479

1680059941916

选择需要的js效果,打开html文件

  • 根据引入的css文件、js文件位置
  • 找解压缩后Swiper文件夹中对应的css、js文件

1680060125496

将其引入在自己的页面中,再复制代码结构修改即可。

②按照规定语法使用

按照demo中html的代码中定义的class

修改自己的代码

(3)拓展

①swiper.css和swiper.min.css是一样的,仅min.css文件经过压缩,因而更小。

②引入时,先引入swiper.js再去引入自己的js

③详细使用见官网:

1680060729613

④更改css样式,可以复制该元素类名,在页面重新修改类样式

  • 样式后+ ! important 提升优先级

    1680061102227

⑤更改js设置,可根据API文档查找属性,进行修改

  • 1680061176138

3.4superslide插件

官网地址:http://www.superslide2.com/

1680061487104

3.5iscroll插件

官网地址:https://github.com/cubiq/iscroll

1680061577685

3.6视频插件

zy.demia.js可用于pc端+移动端的视频显示,相比于pc端< video control>标签,使用该插件可以统一样式,同时无需自己编写诸多代码。

下载地址 : https://github.com/ireaderlab/zyMedia

四、移动端常用开发框架

框架顾名思义是一套架构,基于自身特点向用户提供一套较为完善的解决方案。

  • 框架控制权都在其本身,使用者只能按照规范进行开发

前端常用框架Bootstrap?Vue、Angualer、React等。

前端常用移动端插件swiper、superslide、iscroll等。

4.1框架和插件的区别

框架:大而全,一整套解决方案

插件:小而专一,某个功能的解决方案

4.2Bootstrap框架

官网地址: https://www.bootcss.com/

【注意Bootstrap是基于jQuery实现】

(1)下载框架包

  • 包含css和js文件

(2)引入css和js文件

  • 在自己的html页面中引入bootstrap的js和css

  • 同时注意先引入jquery,再引入boostrap的js

    1680067794216

(3)复制代码结构

到Bootsrap官网上复制代码结构

(4)自行修改样式

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邓六日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值