在Q群有很多人在问touch事件怎么去监控它的左右滑动,于是乎有时间我就萌生了封装touch对象的想法。
利用ES6的新特性class写的touch类,下面来详情介绍一下我的思路:利用ES6的新特性class写的touch类,下面来详情介绍一下我的思路:
下面这个object存放的是用于判断事件的各种参数,它在touchstart、touchmove、touchend的过程中绑定相关数据达到最终的判断结果,具体将过程在后面介绍。
this.obj = { x1: 0, // 初始横坐标 y1: 0, // 初始纵坐标 timeStart: 0, // 初始时间戳 x2: 0, // 结束横坐标 y2: 0, // 结束纵坐标 timeEnd: 0, // 结束时间戳 x: 50, // 横坐标的容错值 y: 50, // 纵坐标的容错值 interval: 200, // 有效时间间隔 sX: 0, // 存放横坐标差 sY: 0, // 存放纵坐标差 sTime: 0, // 存放touch事件的时间长度 getXandYandTime: function () { // 获取坐标差,和touch时间的长度 this.sX = this.x2 - this.x1 this.sY = this.y2 - this.y1 this.sTime = this.timeEnd - this.timeStart }, len: 0 // 记录多少个触摸点 }
下面的object是一个事件委托的列表,每一种事件都用一个列表来存放,避免多次绑定造成的覆盖影响。
this.event = { touch: [], longTouch: [], leftMove: [], rightMove: [], topMove: [], bottomMove: [] }
下面是核心代码,touch事件的判断逻辑。touchstart记录初始坐标值,touchmove跟踪最终坐标点,在touchend或touchcancel根据sX、sY、sTime等参数来判断是什么事件。
init() { this.elm.addEventListener('touchstart', event => { // 保证是单指点击事件 this.obj.len = event.touches.length if (this.obj.len === 1) { this.obj.x1 = this.obj.x2 = event.touches[0].pageX this.obj.y1 = this.obj.y2 = event.touches[0].pageY this.obj.timeStart = new Date().getTime() } }) this.elm.addEventListener('touchmove', (event) => { if (this.obj.len === 1){ this.obj.x2 = event.touches[0].pageX this.obj.y2 = event.touches[0].pageY } }) var touchend = (event) => { if (this.obj.len != 1) { return } let str = '' this.obj.timeEnd = new Date().getTime() this.obj.getXandYandTime() // 判断是否为点击事件 if (Math.abs(this.obj.sX) < this.obj.x && Math.abs(this.obj.sY) < this.obj.y){ if (this.obj.sTime < this.obj.interval) { // console.log('点击事件') str = 'touch' } else { // console.log('长按事件') str = 'longTouch' } } else { if (Math.abs(this.obj.sX) > Math.abs(this.obj.sY)) { if (this.obj.sX > 0) { // console.log('右滑事件') str = 'rightMove' } else { // console.log('左滑事件') str = 'leftMove' } } else { if (this.obj.sY > 0) { // console.log('下滑事件') str = 'bottomMove' } else { // console.log('上滑事件') str = 'topMove' } } } this.mapEvent(str, event) } this.elm.addEventListener('touchend', (event) => { touchend.call(this, event) }) this.elm.addEventListener('touchcancel', (event) => { touchend.call(this, event) }) }
上面介绍了自定义touch事件的判断,接下来看看事件的绑定和解绑,从下面三个方法可以看出来,on将要绑定的事件委托压入数组,off将为委托清空,执行的时候讲列表的函数都执行一次,默认传入event参数。
// 绑定自定义事件 on(str, fn) { this.event[str].push(fn) return this } // 解绑自定义事件 off(str) { this.event[str] = [] return this } // 执行自定义事件 mapEvent(str, event) { for(let val of this.event[str]){ val(event) } }
最后附上全部的代码:
class touch { constructor(elm) { this.elm = elm this.obj = { x1: 0, // 初始横坐标 y1: 0, // 初始纵坐标 timeStart: 0, // 初始时间戳 x2: 0, // 结束横坐标 y2: 0, // 结束纵坐标 timeEnd: 0, // 结束时间戳 x: 50, // 横坐标的容错值 y: 50, // 纵坐标的容错值 interval: 200, // 有效时间间隔 sX: 0, // 存放横坐标差 sY: 0, // 存放纵坐标差 sTime: 0, // 存放touch事件的时间长度 getXandYandTime: function () { console.log(this) this.sX = this.x2 - this.x1 this.sY = this.y2 - this.y1 this.sTime = this.timeEnd - this.timeStart }, len: 0 // 记录多少个触摸点 } // 事件代理列表 this.event = { touch: [], longTouch: [], leftMove: [], rightMove: [], topMove: [], bottomMove: [] } this.init() } // 初始化绑定touchstart、touchmove、touchend事件,用于判断用户执行的操作 init() { this.elm.addEventListener('touchstart', event => { // 保证是单指点击事件 this.obj.len = event.touches.length if (this.obj.len === 1) { this.obj.x1 = this.obj.x2 = event.touches[0].pageX this.obj.y1 = this.obj.y2 = event.touches[0].pageY this.obj.timeStart = new Date().getTime() } }) this.elm.addEventListener('touchmove', (event) => { if (this.obj.len === 1){ this.obj.x2 = event.touches[0].pageX this.obj.y2 = event.touches[0].pageY } }) var touchend = (event) => { if (this.obj.len != 1) { return } let str = '' this.obj.timeEnd = new Date().getTime() this.obj.getXandYandTime() // 判断是否为点击事件 if (Math.abs(this.obj.sX) < this.obj.x && Math.abs(this.obj.sY) < this.obj.y){ if (this.obj.sTime < this.obj.interval) { // console.log('点击事件') str = 'touch' } else { // console.log('长按事件') str = 'longTouch' } } else { if (Math.abs(this.obj.sX) > Math.abs(this.obj.sY)) { if (this.obj.sX > 0) { // console.log('右滑事件') str = 'rightMove' } else { // console.log('左滑事件') str = 'leftMove' } } else { if (this.obj.sY > 0) { // console.log('下滑事件') str = 'bottomMove' } else { // console.log('上滑事件') str = 'topMove' } } } this.mapEvent(str, event) } this.elm.addEventListener('touchend', (event) => { touchend.call(this, event) }) this.elm.addEventListener('touchcancel', (event) => { touchend.call(this, event) }) } // 绑定自定义事件 on(str, fn) { this.event[str].push(fn) return this } // 解绑自定义事件 off(str) { this.event[str] = [] return this } // 执行自定义事件 mapEvent(str, event) { for(let val of this.event[str]){ val(event) } } }
调用方式:
var t = new touch(document.getElementsByClassName('test')[0]).on('touch', event => { console.log('touch') }).on('leftMove', event => { console.log('leftMove') }).off('touch')