一、触屏事件
在移动端,浏览器具有良好的兼容性,所以原生 js 的书写效果可以在移动端使用,我们知道移动端最大的特点就是 可以直接用手指触发事件,因此就需要用到触屏事件。
touch对象是一个触摸点,这个触摸点可以是一个手指,也可以是触摸笔。触屏事件可以响应用户手指或者触摸笔对屏幕或者触控板的操作。
触屏事件包括以下三种:
- touchstart:手指触摸到DOM元素上时触发
- touchmove:手指在DOM元素上滑动时触发
- touchend:手指从DOM元素上离开时触发
二、触屏事件(touchEvent)对象
这是一类描述手指在触摸平面(屏幕、触摸板等)状态变化的事件。这类事件用于描述一个或多个触点,使得开发者更容易检测触点的移动、增加、减少等。
- touches:正在触摸屏幕的所有手指的一个列表
- targetTouches:正在触摸当前 DOM 元素手指的一个列表
- changedTouches:手指状态发生了改变的的列表,从无到有,从有到无的变化
<body>
<div></div>
<script>
var div = document.querySelector('div');
div.addEventListener('touchstart', function(e) {
console.log('我被摸了');
// touches 正在触摸屏幕的所有手指列表
console.log(e);
// targetTouches正在触摸当前DOM元素的手指列表 最常用
// 如果监听的是一个DOM元素 则他们两个是一样的
// changedTouches 手指状态发生了改变的列表 从有到无 从无到有
console.log(e.targetTouches[0]);
// 上面得到的是当前正在触摸元素的第一个手指信息,包括触摸点距离页面的坐标、距离屏幕的坐标等
});
div.addEventListener('touchmove', function() {
console.log('手指在盒子上移动');
});
div.addEventListener('touchend', function(e) {
console.log(e);
// 当手指离开屏幕的时候,就没有touches 和 targetTouches 但是会有 changedTouches
})
</script>
</body>
手指离开时触发 touchend的事件
三、常见特效
以前做过开关灯的案例,如下:
<body>
<button id="btn">开关</button>
<script>
var btn = document.getElementById('btn');
var body = document.querySelector('body');
var flag = false;
btn.onclick = function() {
if (flag === false) {
body.style.backgroundColor = 'black';
flag = true;
} else {
body.style.backgroundColor = 'white';
flag = false;
}
}
</script>
</body>
当鼠标点击开关后,页面背景颜色由白色变为黑色,或者由黑色变为白色,实现一种开关灯的效果。在这里需要用到一个变量 flag 来判断当前元素是否有这个属性或类,实现循环点击改变背景颜色的效果,显然这样做代码比较多。移动端就使用了 classList 属性,方便的实现属性的添加( element.classList.add() )、移除( element.classList.remove() )、切换( element.classList.toggle() 如果有这个类就删除,如果没有这个类就添加)。
下面利用classList属性实现开关灯和添加、移除某个类名:
<body>
<div class="one two"></div>
<button>开关灯</button>
<script>
// classList 返回元素的类名
var div = document.querySelector('div');
var btn = document.querySelector('button');
console.log(div.classList[1]);
// 1.添加类名 实在后面追加类名,不会覆盖原来的类名 前面不需要加 .
div.classList.add('three');
// console.log(div.classList);
// 2.移除某个类名
// div.classList.remove('one');
// 3.切换类 如果有这个类就删除 没有就添加
btn.addEventListener('click', function() {
document.body.classList.toggle('bg');
// .bg 这个类的样式已经写在<style></style>标签内
});
</script>
</body>
四、拖动元素
- 拖动原理:手指在屏幕上移动过程中,计算手指移动的距离,元素最终位置 = 元素的初始位置 + 手指移动的距离
- 这里需要用到 触屏事件 touchstart、touchmove、touchend
拖动元素需要知道元素的坐标,因此要用到触屏事件对象中的 targetTouches[0]中的pageX,pageY - 手指移动距离 = 手指现在的位置 - 手指之前的位置
- 拖动三部曲:
触摸元素 touchstart: 获取手指初始坐标,同时获得盒子原来的位置
移动手指 touchmove: 计算手指移动的距离,并移动盒子
手指离开 touchend
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>移动端拖动元素</title>
<style>
div {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
// 手指移动会触发滚动屏幕,所以要阻止默认滚动屏幕e.preventDefault()
<script>
var div = document.querySelector('div');
// 定义全局变量
var startX = 0; // 手指的初始坐标
var startY = 0;
var x = 0; // 盒子的初始坐标
var y = 0;
div.addEventListener('touchstart', function(e) {
// 获取手指的初始坐标
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;
// 获取盒子的初始坐标
x = this.offsetLeft;
y = this.offsetTop;
});
div.addEventListener('touchmove', function(e) {
// 手指移动的距离 = 手指现在的位置 - 手指原来的位置
var moveX = e.targetTouches[0].pageX - startX;
var moveY = e.targetTouches[0].pageY - startY;
// 盒子移动的距离 = 盒子原来的位置 + 手指移动的距离
// 盒子加了定位 就通过修改 left 和 top 值进行移动
this.style.left = x + moveX + 'px';
this.style.top = y + moveY + 'px';
e.preventDefault();
});
</script>
</body>
</html>
五、点击延时300ms问题解决方案
原因:移动端与WEB端不同,移动端浏览网站页面时可能会比较小,看不清,这时用户就会用手指放大页面,浏览完成以后在屏幕被双击(double tap to zoom)就可以缩放页面,因此在手指点击屏幕一次时,内部程序会等待 300ms ,看是否在这段时间之内还有下一次点击,这就导致了点击一次会有延时效果。
解决方案
- 禁用缩放:浏览器禁用默认的双击行为就可以去掉延时,利用视口标签设置禁止用户缩放属性
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
- 利用touch事件封装(简单理解即可)
原理:①当手指触摸屏幕时,记录当前时间
②当手指离开时,用离开时间 - 触屏时间
③如果上面的计算结果小于150ms 并且没有滑动屏幕则视为点击事件
//封装一个函数
function tap(obj, callback) {
var isMove = false;
var startTime = 0; // 记录触摸时的时间变量
obj.addEventListener('touchstart', function(e) {
startTime = Date.now(); //记录触摸时间
});
obj.addEventListener('touchmove', function(e) {
isMove = true;
// 看是否滑动 如果滑动就不是点击事件
});
obj.addEventListener('touchend', function(e) {
// 没有滑动 并且 时间差小于 150ms 则视为点击事件
if(!isMove && (Date.now() - startTime) < 150){
callback && callback(); // 执行回调函数
}
isMove = false; // 取反 重置
startTime = 0;
});
}
// 调用
tap(div, function() {
// 这里放执行代码
});
- 使用 fastclick 插件解决(最常用)
在网上找到这个插件下载,然后在代码中引用做适当修改即可,地址:https://github.com/ftlabs/fastclick
六、本地存储
本地存储的特性:
① 数据存储在用户浏览器中
② 设置读取方便,甚至页面刷新也不会丢失数据
③ 容量较大,window.sessionStorage 5M 左右
window.localStorage 20M左右
window.sessionStorage
特性:
① 生命周期到关闭浏览器窗口为止
② 在同一个窗口或页面下数据可以共享
③ 数据以键值对的形式存储使用
存储数据的方法:
sessionStorage.setItem(key, value)
获取数据的方法:
sessionStorage.getItem(key)
删除数据的方法:
sessionStorage.removeItem(key)
清除所有数据的方法:
sessionStorage.clear()
window.localStorage
特性:
① 生命周期永久生效,除非手动删除,否则关闭页面也会存在
② 可以多个窗口或页面共享,同一个浏览器也可以共享
③ 以键值对的形式存储数据
存储数据、获取数据、删除数据的方法类似window.sessionStorage,这里不再赘述。