在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')