手机端封装一些常用事件

手机自定义事件

手机常用的触屏事件只有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
    } 
  })
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容