移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定clickmouseover等事件来完成。但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件。处理touch事件能跟踪到屏幕滑动的每根手指。

以下是四种touch事件

  • touchstart:手指放到屏幕上时触发
  • touchmove:手指在屏幕上滑动式触发
  • touchend:手指离开屏幕时触发
  • touchcancel:系统取消touch事件的时候触发,这个好像比较少用

事件对象

每个触摸事件被触发后,会生成一个event对象,event对象里额外包括以下三个触摸列表

  • touches:当前屏幕上所有手指的列表
  • targetTouches:当前dom元素上手指的列表,尽量使用这个代替touches
  • changedTouches:涉及当前事件的手指的列表,尽量使用这个代替touches

touch对象属性

这些列表里的每次触摸由touch对象组成,touch对象里包含着触摸信息,主要属性如下:

  • clientX / clientY:触摸点相对浏览器窗口的位置
  • pageX / pageY:触摸点相对于页面的位置
  • screenX / screenY:触摸点相对于屏幕的位置
  • identifier:touch对象的ID
  • target:当前的DOM元素

注意:

手指在滑动整个屏幕时,会影响浏览器的行为,比如滚动和缩放。所以在调用touch事件时,要注意禁止缩放和滚动。

  1. 禁止缩放,通过meta元标签来设置。

    1
    <meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no" />
  2. 禁止滚动,preventDefault是阻止默认行为,touch事件的默认行为就是滚动。
    1
    event.preventDefault();

案例:

下面给出一个案例,需在移动设备上才能看出效果。

1.定义touchstart的事件处理函数,并绑定事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (!!self.touch) self.slider.addEventListener('touchstart',self.events,false);
 
//定义touchstart的事件处理函数
start: function(event) {
    event.preventDefault();                                     // 阻止触摸事件的默认动作,即阻止滚屏
    var touch = event.touches[0];                               // touches数组对象获得屏幕上所有的touch,取第一个touch
 
    // 取第一个touch的坐标值
    startPos = {
        x: touch.pageX,
        y: touch.pageY,
        time: +new Date
    };   
 
    // 绑定事件
    this.slider.addEventListener('touchmove',this,false);
    this.slider.addEventListener('touchend',this,false);
},
  • 触发touchstart事件后,会产生一个event对象;
  • event对象里包括触摸列表;
  • 获得屏幕上的第一个touch,并记下其pageXpageY的坐标;
  • 此时绑定touchmovetouchend事件;

2.定义手指在屏幕上移动的事件,定义touchmove函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//移动
move: function(event) {
    // 阻止触摸事件的默认行为,即阻止滚屏
    event.preventDefault();
 
    // 当屏幕有多个touch或者页面被缩放过,就不执行move操作
    if (event.touches.length > 1 || event.scale && event.scale !== 1) return;
    var touch = event.touches[0];
    endPos = {
        x: touch.pageX - startPos.x,
        y: touch.pageY - startPos.y
    };
 
    // 执行操作,使元素移动
    this.slider.className = 'cnt';
    this.slider.style.left = -this.index * 600 + endPos.x + 'px';
},

同样首先阻止页面的滚屏行为:

  • touchmove触发后,会生成一个event对象;
  • 在event对象中获取touches触屏列表,取得第一个touch;
  • 并记下pageX和pageY的坐标,算出差值,得出手指滑动的偏移量,使当前DOM元素滑动。

3.定义手指从屏幕上拿起的事件,定义touchend函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 滑动释放
end: function(event){
    // 滑动的持续时间
    var duration = +new Date - startPos.time;
    this.icon[this.index].className = '';
    if (Number(duration) > 100) {
        // 判断是左移还是右移,当偏移量大于50时执行
        if (endPos.x > 50) {
            if (this.index !== 0) this.index -= 1;
        } else if(endPos.x < -50) {
            if(this.index !== 4) this.index += 1;
        }
    }
 
    this.slider.className = 'cnt f-anim';
    this.slider.style.left = -this.index*600 + 'px';
    this.icon[this.index].className = 'curr';
 
    // 解绑事件
    this.slider.removeEventListener('touchmove', this, false);
    this.slider.removeEventListener('touchend', this, false);
},

手指离开屏幕后,所执行的函数。

  • 这里先判断手指停留屏幕上的时间,如果时间太短,则不执行该函数;
  • 再判断手指是左滑动还是右滑动,分别执行不同的操作;
  • 最后很重要的一点是移除touchmove,touchend绑定事件;

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" Content="text/html; charset=utf-8;" />
 
        <title>移动端触摸滑动</title>
        <meta name="author" content="rainna" />
        <meta name="keywords" content="rainna's js lib" />
        <meta name="description" content="移动端触摸滑动" />
        <meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no" />
 
        <style>
        *{margin:0;padding:0;}
        li{list-style:none;}
 
        .m-slider{width:600px;margin:50px 20px;overflow:hidden;}
        .m-slider .cnt{position:relative;left:0;width:3000px;}
        .m-slider .cnt li{float:left;width:600px;}
        .m-slider .cnt img{display:block;width:100%;height:450px;}
        .m-slider .cnt p{margin:20px 0;}
        .m-slider .icons{text-align:center;color:#000;}
        .m-slider .icons span{margin:0 5px;}
        .m-slider .icons .curr{color:red;}
        .f-anim{-webkit-transition:left .2s linear;}
        </style>
    </head>
 
    <body>
        <div class="m-slider">
            <ul class="cnt" id="slider">
                <li>
                    <img src="http://levi.yii.so/wp-content/uploads/2014/08/o_3068640196117481166.jpg" alt="" />
                    <p>20140813镜面的世界,终究只是倒影。看得到你的身影,却触摸不到你的未来</p>
                </li>
                <li>
                    <img src="http://levi.yii.so/wp-content/uploads/2014/08/o_4798022453110310215.jpg" alt="" />
                    <p>20140812锡林浩特前往东乌旗S101必经之处,一条极美的铁路。铁路下面是个小型的盐沼,淡淡的有了一丝天空之境的感觉。可惜在此玩了一个小时也没有看见一列火车经过,只好继续赶往东乌旗。</p>
                </li>
                <li>
                    <img src="http://levi.yii.so/wp-content/uploads/2014/08/o_6608946691259322175.jpg" alt="" />
                    <p>20140811水的颜色为什么那么蓝,我也纳闷,反正自然饱和度和对比度拉完就是这个颜色的</p>
                </li>
                <li>
                    <img src="http://levi.yii.so/wp-content/uploads/2014/08/o_6619295294699949331.jpg" alt="" />
                    <p>海洋星球3重庆天气热得我想卧轨自杀</p>
                </li>
                <li>
                    <img src="http://levi.yii.so/wp-content/uploads/2014/08/o_3068640196117481166.jpg" alt="" />
                    <p>以上这些作品分别来自两位设计师作为观者,您能否通过设计风格进行区分</p>
                </li>
            </ul>
 
            <div class="icons" id="icons">
                <span class="curr">1</span>
                <span>2</span>
                <span>3</span>
                <span>4</span>
                <span>5</span>
            </div>
        </div>
 
        <script>
        var slider = {
            // 判断设备是否支持touch事件
            touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
            slider: document.getElementById('slider'),
 
            // 事件
            events: {
                index: 0,                                       // 显示元素的索引
                slider: this.slider,                            // this为slider对象
                icons: document.getElementById('icons'),
                icon: this.icons.getElementsByTagName('span'),
                handleEvent: function(event) {
                    // this指events对象
                    var self = this;
 
                    if (event.type == 'touchstart') {
                        self.start(event);
                    } else if(event.type == 'touchmove') {
                        self.move(event);
                    } else if(event.type == 'touchend') {
                        self.end(event);
                    }
                },
 
                // 滑动开始
                start: function(event) {
                    event.preventDefault();                      // 阻止触摸事件的默认动作,即阻止滚屏
                    var touch = event.touches[0];                // touches数组对象获得屏幕上所有的touch,取第一个touch
                    startPos = {                                 // 取第一个touch的坐标值
                        x: touch.pageX,
                        y: touch.pageY,
                        time: +new Date
                    };
 
                    // 绑定事件
                    this.slider.addEventListener('touchmove', this, false);
                    this.slider.addEventListener('touchend', this, false);
                },
 
                // 移动
                move: function(event) {
                    event.preventDefault();                      // 阻止触摸事件的默认行为,即阻止滚屏
 
                    // 当屏幕有多个touch或者页面被缩放过,就不执行move操作
                    if (event.touches.length > 1 || event.scale && event.scale !== 1) return;
                    var touch = event.touches[0];
                    endPos = {
                        x: touch.pageX - startPos.x,
                        y: touch.pageY - startPos.y
                    };
 
                    // 执行操作,使元素移动
                    this.slider.className = 'cnt';
                    this.slider.style.left = -this.index * 600 + endPos.x + 'px';
                },
 
                // 滑动释放
                end: function(event) {
                    var duration = +new Date - startPos.time;    // 滑动的持续时间
 
                    this.icon[this.index].className = '';
                    if (Number(duration) > 100) {
                        // 判断是左移还是右移,当偏移量大于50时执行
                        if (endPos.x > 50) {
                            if(this.index !== 0) this.index -= 1;
                        } else if(endPos.x < -50) {
                            if (this.index !== 4) this.index += 1;
                        }
                    }
 
                    this.slider.className = 'cnt f-anim';
                    this.slider.style.left = -this.index*600 + 'px';
                    this.icon[this.index].className = 'curr';
 
                    // 解绑事件
                    this.slider.removeEventListener('touchmove', this, false);
                    this.slider.removeEventListener('touchend', this, false);
                }
            },
 
            // 初始化
            init: function() {
                // this指slider对象
                var self = this;
 
                // addEventListener第二个参数可以传一个对象,会调用该对象的handleEvent属性
                if(!!self.touch) self.slider.addEventListener('touchstart', self.events, false);
            }
        };
 
        slider.init();
        </script>
    </body>
</html>

js移动端触屏事件的更多相关文章

  1. Hammer.js移动端触屏框架的使用

    hammer.js是一个多点触摸手势库,能够为网页加入Tap.Double Tap.Swipe.Hold.Pinch.Drag等多点触摸事件,免去自己监听底层touchstart.touchmove. ...

  2. JS移动端滑屏事件

    来看看在pc上面的几个事件:onmousedown,onmousemove,onmouseup 我相信大家对这几个事件一定不陌生,第一个onmousedown表示鼠标按下,第二个onmousemove ...

  3. 移动端触屏滑动,JS事件

    先了解下 移动端的触屏滑动 毕竟这玩意其实和PC端还是有一定的区别的 hh 整理了下网上的资料放一放 移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等 ...

  4. JS案例之5——移动端触屏滑动

    移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等事件来完成.但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件.处理touch事件 ...

  5. 从零开始学 Web 之 移动Web(二)JD移动端网页,移动触屏事件

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  6. (转)js的左右滑动触屏事件

    原文:http://blog.sina.com.cn/s/blog_6a0a183f0100zsfk.html (2012-01-20 08:55:53) 转载▼ 标签: 移动设备 触屏事件 杂谈 分 ...

  7. js触屏事件

    js的左右滑动触屏事件,主要有三个事件:touchstart,touchmove,touchend.这三个事件最重要的属性是 pageX和 pageY,表示X,Y坐标. touchstart在触摸开始 ...

  8. 移动端touch触屏滑动事件、滑动触屏事件监听!

    一.触摸事件 ontouchstart.ontouchmove.ontouchend.ontouchcancel 目前移动端浏览器均支持这4个触摸事件,包括IE.由于触屏也支持MouseEvent,因 ...

  9. 移动端触屏click点击事件延迟问题,以及tap的解决方案

    在移动端 触屏click事件虽然也会响应,但是总感觉是有延迟,一直听说click事件在手机上有200~300毫秒的延迟问题,亲自测了一下,在pc端模拟手机的话是测不出来的,但是用手机测试时发现延迟非常 ...

随机推荐

  1. springcloud(十二)-springcloud-config统一管理微服务配置

    1.为什么要统一管理微服务配置 对于传统的单体应用,常使用配置文件管理所有配置.例如一个SpringBoot开发的单体应用,可将配置内容放在application.yml文件中.如果需要切换环境,可设 ...

  2. spark内存管理详解

    Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色.理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优.本文旨在梳理出 ...

  3. jquery.validate.js表单验证 jquery.validate.js的用法

    jquery.validate.js这个插件已经用了2年多了,是一个不可多得的表单验证最方便快捷的插件.基于jquery的小插件,基本小白一学就会上手,对于项目表单页面比较多,元素比较多的校验,该插件 ...

  4. 创建LEANGOO看板

    转自:https://www.leangoo.com/leangoo_guide/leangoo_guide_create_kanban.html#toggle-id-3 Leangoo使用看板来管理 ...

  5. webpack升级4出现的问题

    webpack3升级到4出现了很多问题,经过验证报错信息如下 1 Module parse failed: Unexpected token (:) You may need an appropria ...

  6. 2019-11-29-解决从旧格式的-csproj-迁移到新格式的-csproj-格式-AssemblyInfo-文件值重复问题...

    title author date CreateTime categories 解决从旧格式的 csproj 迁移到新格式的 csproj 格式 AssemblyInfo 文件值重复问题 lindex ...

  7. mysql精准模糊查询使用CONCAT加占位符(下划线“_”)的使用,直接限定了长度和格式

    比如现在有张表t_user,如下:(表中只是引用某某某的话,并无恶意) id name 1 司马懿 2 司马老贼 3 司马老贼OR司马懿 4 司马大叔 1.模糊查询一般用的模糊查询都是like关键词, ...

  8. MySQL查询多行重复数据SQL

    1 详见如下 SELECT day_time,`city_code`,count(1) as num FROM t_user_register_analyse GROUP BY `day_time`, ...

  9. 逆向破解H.Koenig 遥控器 Part 2

    逆向破解H.Koenig 遥控器 Part 2 到目前为止,我们已经知道了RF收发器的安装过程,下面是我们所掌握的东西 : l 无线电收发器是一个Avantcom A7105 l 调制是FSK l 频 ...

  10. HttpServletResponse 返回的json数据不是json字符串,而是json对象

    今天在改一个bug 情况: 在spring boot中写了一个类Result ,用来统一封装 各个API响应结果 , 其中重写了toString()方法来返回 json字符串 . 在正常情况下,从其它 ...