移动互联网终端的touch事件
touchstart 手指触摸屏幕的时候执行
touchmove 手指在屏幕上移动的时候执行
touchend 手指离开屏幕的时候执行
touchcancel 事件被强制终止的时候执行 (来电话了 短信 按home)
每个触摸事件都包括了三个触摸列表:
- touches :当前位于屏幕上的所有手指的一个列表。
- targetTouches :位于当前DOM元素上的手指的一个列表。
- changedTouches :涉及当前事件的手指的一个列表。
这些列表由包含了触摸信息的对象组成:
- identifier :一个数值,唯一标识触摸会话(touch session)中的当前手指。
- target :DOM元素,是动作所针对的目标。
- 客户/页面/屏幕坐标 :动作在屏幕上发生的位置。
- 半径坐标和 rotationAngle :画出大约相当于手指形状的椭圆形。
深入了解touch事件之前 有必要先了解 touch对象 ;
touch对象用来封装一次屏幕触摸,一般来自于手指。
它在touch事件触发的时候产生,可以通过touch事件处理器(event handler)机制的event对象取到;(一般是通过event.changedTouches属性)。
这个对象包括一些重要的属性:
client / clientY:触摸点相对于浏览器窗口viewport的位置
pageX / pageY:触摸点相对于页面的位置
screenX /screenY:触摸点相对于屏幕的位置
identifier: touch对象的unique ID
移动平台 对meta标签的定义(很多种 ,先了解一种写法)
<meta name="viewport" content="width=device-width, initial-scale=1.0,
maximum-scale=1.0, user-scalable=no" />
user-scalable – // 用户是否可以手动缩放 (no,yes)
maximum-scale – // 允许用户缩放到的最大比例
initial-scale – // 初始的缩放比例 (范围从 > 0 到 10)
demo1
一个div;手指触摸时显示 ;手指移动 div也跟着移动 ;手指离开 div消失
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<title>touch</title>
<style>
html,body,div{
margin: 0;
padding: 0;
}
#box{
width: 50px;
height: 50px;
background-color: pink;
display: none;
position: absolute;
}
.show{
//权重 !important
display: block !important;
}
</style>
</head>
<body>
<div id="box">
</div>
<script>
var box = document.querySelector("#box");
document.addEventListener("touchstart",function (e) {
box.className = "show";
var touch = e.changedTouches[0];
box.style.left = touch.pageX - box.offsetWidth / 2 + "px";
box.style.top = touch.pageY - box.offsetHeight / 2 +"px";
})
document.addEventListener("touchmove",function (e) {
var touch = e.changedTouches[0];
box.style.left = touch.pageX - box.offsetWidth / 2 + "px";
box.style.top = touch.pageY - box.offsetHeight / 2 +"px";
})
document.addEventListener("touchend",function (e) {
box.className = "";
})
</script>
</body>
</html>
demo2
做一个入下图所示无滚动条 可左右滑动的 且无论字数间距固定 不会换行的导航栏
代码如下
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>
<title>Document</title>
<style type="text/css">
html,body,div,ul,li{
margin: 0;
padding: 0;
}
#topbar{
width: 100%;
height: 44px;
overflow: hidden;
}
#nav{
height: 55px;
overflow: auto;
background-color: #0FA9D8;
}
#nav ul{
white-space: nowrap;
/*width: auto;*/
}
#nav ul li{
display: inline-block;
height: 44px;
line-height: 44px;
padding: 0 30px;
}
</style>
</head>
<body>
<div id="topbar">
<nav id="nav">
<ul>
<li>娱乐头条</li>
<li>军事</li>
<li>历史</li>
<li>新闻</li>
<li>美图</li>
<li>旅游</li>
</ul>
</nav>
</div>
</body>
<script>
var ul = document.querySelector("ul");
ul.addEventListener("touchstart",function(e){
this.startTouch = e.changedTouches[0];
})
ul.addEventListener("touchmove",function(e){
var touch = e.changedTouches[0];
if(Math.abs(touch.pageX-this.startTouch.pageX)>10){
this.isMove = true;
}
})
ul.addEventListener("touchend",function(e){
this.endTouch = e.changedTouches[0];
if(Math.abs(this.endTouch.pageX-this.startTouch.pageX)<10 && !this.isMove){
console.log("tap")
}else{
console.log("move");
}
if (e.target.nodeName=="LI") {
console.log(e.target.innerHTML);
}
})
</script>
</html>
有一个问题 this.startTouch = e.changedTouches[0];这个获取到的是第一次触摸的事件 ,以后 全是以此为参照 ~有时间请教下别人
待理解的touch.js
/**
* Created by lovering on 16/9/20.
*/
(function () {
var typeObj = {
tap: true, //点击 和 抬起的位置 误差不超过容错范围 即算tap
doubleTap: true, //两次tap 时间在300ms 之内 算doubleTap
swiperLeft: true, //抬起的位置的X 相对于 开始的位置的 X 的差值 为正 并且 滑动距离大于某个值(40px) Y上线误差不能超过20px(误差为40px)
swiperRight: true, //抬起的位置的X 相对于 开始的位置的 X 的差值 为负 并且 滑动距离大于某个值(40px) Y上线误差不能超过20px(误差为40px)
swiperDown: true, //抬起的位置的Y 相对于 开始的位置的 Y 的差值 为正 并且 滑动距离大于某个值(40px) X上线误差不能超过20px(误差为40px)
swiperUp: true //抬起的位置的Y 相对于 开始的位置的 Y 的差值 为负 并且 滑动距离大于某个值(40px) X上线误差不能超过20px(误差为40px)
}
var eventFn = {
tap : function (e,callback) {
if (Math.abs(this._endTouch.pageX - this._startTouch.pageX) <= 5 && Math.abs(this._endTouch.pageY - this._startTouch.pageY) <= 5 && !this._isMove){
if (callback){
callback(e);
}
}
},
doubleTap : function (e,callback) {
var t = this;
isDouble(function () {
//用自定义属性来存储点击的次数
t._tapNum += 1;
//判断是否开启过定时器 如果没开起过则进入判断 开启定时器 如果定时器开启说明当前为第二次点击
if (!t._timer){
t._timer = setTimeout(function () {
//300ms后判断当前的点击次数是否为2 如果为2则说明在300ms内点击了两次
//同时判断callback 是否存在 如存在说明外面给元素绑定过双击事件
//两个条件都满足的情况下 则回调双击事件的回调函数.
if (t._tapNum == 2 && callback){
callback(e);
}else if (t._tapNum == 1){
//如果当前点击次数为1 说明没有进行双击 当前为单击 调用单击判断的方法 进行单击函数的回调
eventFn.tap.call(t,e,t._evevtType["tap"]);
}
//不管是否在300ms 内双击 我们都需要将 点击次数清零 定时器清除 并置空 以便下个周期 从新判断使用
t._tapNum = 0;
clearTimeout(t._timer);
t._timer = null;
},300)
}
});
function isDouble(callback) {
if (Math.abs(t._endTouch.pageX - t._startTouch.pageX) <= 5 && Math.abs(t._endTouch.pageY - t._startTouch.pageY) <= 5 && !t._isMove){
callback();
}
}
},
swiperLeft : function (e,callback) {
if (this._endTouch.pageX - this._startTouch.pageX < -40 && Math.abs(this._endTouch.pageY - this._startTouch.pageY) <= 20){
if (callback){
callback(e);
}
// callback && callback(e);
//
// callback ? callback(e) : null;
}
},
swiperRight : function (e,callback) {
if (this._endTouch.pageX - this._startTouch.pageX > 40 && Math.abs(this._endTouch.pageY - this._startTouch.pageY) <= 20){
if (callback){
callback(e);
}
}
},
swiperDown : function (e,callback) {
if (this._endTouch.pageY - this._startTouch.pageY > 40 && Math.abs(this._endTouch.pageX - this._startTouch.pageX) <= 20){
if (callback){
callback(e);
}
}
},
swiperUp : function (e,callback) {
if (this._endTouch.pageY - this._startTouch.pageY < -40 && Math.abs(this._endTouch.pageX - this._startTouch.pageX) <= 20){
if (callback){
callback(e);
}
}
}
};
HTMLElement.prototype.addEventListener = function (eventType,callback) {
if (typeObj[eventType]){
if (!this._isBind){
this._isBind = true;
this._evevtType = {};
//第一次绑定的时候设置一个自定义属性用来存储点击次数 以便后面判断双击时使用
this._tapNum = 0;
//在第一次绑定的时候 给绑定元素设置一个对象的自定义属性 以绑定的事件类型为属性名 以 对应事件类型的callback 为属性值
//把绑定过的事件进行存储.
this._evevtType[eventType] = callback;
EventTarget.prototype.addEventListener.call(this,"touchstart",function (e) {
this._startTouch = e.targetTouches[0];
this._isMove = false;
});
EventTarget.prototype.addEventListener.call(this,"touchmove",function (e) {
var moveTouch = e.targetTouches[0];
if (Math.abs(moveTouch.pageX - this._startTouch.pageX) > 5 && Math.abs(moveTouch.pageY - this._startTouch.pageY) > 5){
this._isMove = true;
}
});
EventTarget.prototype.addEventListener.call(this,"touchend",function (e) {
this._endTouch = e.changedTouches[0];
for (var key in eventFn){
if (key != "tap"){
eventFn[key].call(this,e,this._evevtType[key]);
}
}
});
}else {
//在第一次之后我们对每次绑定的事件进行存储
this._evevtType[eventType] = callback;
}
}else {
EventTarget.prototype.addEventListener.call(this,eventType,callback);
}
}
HTMLElement.prototype.removeEventListener = function (eventType,callback) {
if (typeObj[eventType]){
if (this._evevtType[eventType] && this._evevtType[eventType] == callback){
delete this._evevtType[eventType];
}
}else {
EventTarget.prototype.removeEventListener.call(this,eventType,callback);
}
}
})();