手机自定义事件
手机常用的触屏事件只有touchstart,touchmove,touchend,其它需要常用的就需要自己封装
常用事件
使用时调用的方法,用的是对象的方法,就不需要在传参方法时,需要注意先后顺序了
funciton touchEvent(init){
var el = init.el;
var isTap = true; //是否发生点击(在按下和抬起之间没有发生过移动,就是点击)
var isDblTap = false;//默认不是双击
var lastPoint = {}; //记录最后次手指所在位置
var startPoint = {};//记录touchstart按下时的手指所在位置
var dbTimer = 0;//定义是否是双击时间
var longTapTimer = 0;//定义是否是长按时间
el.addEventListener('touchstart',function(e){
lastPoint = {
x: Math.round(e.changedTouches[0].clientX) //event对象获取到当前手指位置
y: Math.round(e.changedTouches[0].clientY)
};
startPoint = {
x: Math.round(e.changedTouches[0].clientX)
y: Math.round(e.changedTouches[0].clientY)
};
longTapTimer = setTimeout(function(){
init.longTap&&init.longTap.call(el,e);
},750)
//定义超过750ms,并且长按函数存在就执行长按函数
});
/* 安卓下,在touchstart时,触发面积过大时很容易一块触发move */
el.addEventListener('touchmove',function(e){
//获取移动过程的手指位置
var nowPoint = {
x: Math.round(e.changedTouches[0].clientX)
y: Math.round(e.changedTouches[0].clientY)
}
if(nowPoint.x == lastPoint.x&&nowPoint.y == lastPoint.y){
return; //手指没有移动就return,不执行操作
}
if(Math.abs(nowPoint.x - startPoint.x) > 5
&&Math.abs(nowPoint.y - startPoint.y)>5)){
clearTimeout(longTapTimer);
}
//如果移动的距离超过5,就判断不是长按了,关闭长按的定时器
lastPoint = {x: nowPoint.x, y: nowPoint.y}
//最后一次点击位置就变成最后一次移动的手指位置
});
el.addEventListener('touchend',function(e){
//抬起的手指位置
var nowPoint = {
x: Math.round(e.changedTouches[0].clientX),
y: Math.round(e.changedTouches[0].clientY)
}
if(Math.abs(nowPoint.x - startPoint.x)<5
&&Math.abs(nowPoint.y - startPoint.y)<5){
isTap = true;
} else {
isTap = false;
}
isTap&&init.tap&&init.tap.call(el,e)
//判断抬起和按下的距离小于5,并且tap事件存在,执行tap事件
//*判断用户是否执行双击操作
if(isTap){
if(isDblTap){
clearTimeout(dbTimer);
init.doubleTap&&init.doubleTap.call(el,e);
isDblTap = false;
} else {
isDblTap = true;
dbTimer = setTimeout(function(){
isDblTap = false;
init.doubleTap&&init.doubleTap.call(el,e);
//init.singleTap&&init.singleTap.call(el,e);
},300)
}
}
//点击后为true,但是isDblTap默认为false走else,在dbTimer 300ms之类再次点击就是,执行双击doubleTap事件,*因为是双击会也触发点击的事件,如果要不冲突就改为执行singleTap单击
if(getDis(nowPoint,startPoint) >= 20){
//在屏幕中滑动了
init.swipe&&init.swipe.call(el,e);;
}
if(nowPoint.x - startPoint.x >= 20){
init.swipeRight&&init.swipeRight.call(el,e);;
} else if(nowPoint.x - startPoint.x <= -20){
init.swipeLeft&&init.swipeLeft.call(el,e);;
}
if(nowPoint.y - startPoint.y >= 20){
init.swipeDown&&init.swipeDown.call(el,e);;
} else if(nowPoint.y - startPoint.y <= -20){
init.swipeUp&&init.swipeUp.call(el,e);
}
//根据滑动的距离和差值来判断是往那边滑动
isTap = true;
});
}
init: {
el: el,//要添加事件的元素
tap: fn,//点击
longTap: fn,//长按
singleTap: fn,//单击
doubleTap: fn,//双击
swipe: fn,//滑动
swipeLeft: fn,//向左滑动
swipeRight: fn,//向右滑动
swipeUp: fn,//向上滑动
swipeDown: fn//向下滑动
}
缩放,旋转
gesture事件:
- gesturestart 当前事件触发时,屏幕上有两根或者两根以上的手指
- gesturechange 触发了gesturestart 之后, 手指坐标发生变化
- gestureend 触发了gesturestart 之后,手指抬起
安卓手机下没有gesture事件(手势事件),就需要自己封装gesture事件
function gesture(init){
var el = init.el;
var isGesture = false;
var startDis = 0;
var startDeg = 0;
el.addEventListener('touchstart',function(e){
if(e.touches.length >= 2){
isGesture = true;
startDis = getDis(e.touches[0],e.touches[1]);
startDeg = getDeg(e.touches[0],e.touches[1]);
init.start&&init.start.call(el,e);
}
});
el.addEventListener('touchmove',function(e){
if(isGesture&&e.touches.length >= 2){
isGesture = true;
var nowDis = getDis(e.touches[0],e.touches[1]);
var nowDeg = getDeg(e.touches[0],e.touches[1]);
e.scale = nowDis/startDis; //2指的距离差值比就是缩放的比例
e.rotation = nowDeg - startDeg; //2指的角度差指变化就是旋转的角度
init.change&&init.change.call(el,e);
}
});
el.addEventListener('touchend',function(e){
if(isGesture){
init.end&&init.end.call(el,e);
}
isGesture = false;
})
function getDis(Point,Point2){ //获取2指之间的距离
return Math.sqrt((Point.pageX - Point2.pageX)*(Point.pageX - Point2.pageX) + (Point.pageY - Point2.pageY)*(Point.pageY - Point2.pageY));
}
function getDeg(Point,Point2){ //
var y = Point.pageY - Point2.pageY;
var x = Point.pageX - Point2.pageX;
return Math.atan2(y,x)/Math.PI*180;
//函数atan2(y,x)中参数的顺序是倒置的,atan2(y,x)计算相当于点(x,y)的角度值
}
}
由于css设置的transform的值获取到的是矩阵,不能反向推出来获取到具体的数值,必须先把transform设置到行间样式上,进行获取
function css(el,attr,val){
var transform = ['rotate','rotateX','rotateY','rotateZ','scale','scaleX','scaleY','skewX','skewY','translateX','translateY','translateZ'];
for(var i = 0; i < transform.length; i++){
if(attr == transform[i]){
return setTransform(el,attr,val);
}
}
};
function setTransform(el,attr,val){
if(!el.transform){
el.transform = {};
//如果元素没有这个自定义属性我们就创建一下,格式是个对象
}
if(typeof val == "undefined"){
return el.transform[attr];
} else {
el.transform[attr] = val;
var value = "";
for(var s in el.transform){
//console.log(s,el.transform[s]);
switch(s){
case "rotate":
case "rotateX":
case "rotateY":
case "rotateZ":
case "skewX":
case "skewY":
value += (s+"("+el.transform[s]+"deg) ");
break;
case "translateX":
case "translateY":
case "translateZ":
value += (s+"("+el.transform[s]+"px) ");
break;
case "scale":
case "scaleX":
case "scaleY":
value += (s+"("+el.transform[s]+") ");
break;
}
}
el.style.WebkitTransform = value;
el.style.MozTransform = value;
el.style.msTransform = value;
el.style.transform = value;
}
}
//这个方法,3个参数就是设置样式,2个参数就是获取样式
使用封装的getsture()方法
/*
init: {
el: 元素,
start: fn,
change: fn,
end: fn
}
*/
function(){
var box = document.querySelector("#box");
var startDeg = 0; //定义一个初始角度;
var startScale = 0;//定义个一个初始缩放比例;
css(box,"scale",100)
css(box."rotate",0);
//调用上面的css方法,设置下行间样式scale,rotate属性;
//*使用gesture方法
gesture({
el: box, //需要动画的元素
start: function(e){ //start就是按下touchstart的执行的,获取到初始的位置和元素的样式
startScale = css(box,"scale") //css这个方法,3个参数就是设置样式,2个参数就是获取样式
startDeg = css(box,"rotate");
},
change: function(e){ //移动的时候 就可以开始发生变化了
css(this,"scale",(e.scale * startScale); //移动产生的缩放比例*默认的缩放当前比例
css(box,"rotate",e.rotation + startDeg); //移动产生的角度变化加上本身的元素的当前角度
}
end: function(e){
//手指抬起要执行的方法,可以根据自己的要求去添加包括以上的start和change
}
})
}