这篇博客,我们来说下,事件当中比较常用的特殊事件 touch。
相信用过 touch 的都知道,这个东西特别的烦,用了它的多少都会出点事。
首先我们肯定一点,这个 touch 是移动端的事件,在 PC 端是用不了的。
然后,这个 touch 事件,跟我们普通的鼠标事件,有一点区别:
首先,touch 事件它支持多点的触摸,因为我们在手机上都用过,比如两个手指缩放。
并且,在支持多点触摸的同时,也就顺便的帮助我们可以做一件事,就是手势。手势在我们平常鼠标上是用不了的。
那么我们先来介绍下,touch 事件分成三个:ontouchstart、ontouchmove、ontouchend。
它跟我们的鼠标事件是对应的,比如:onmousedown、onmousemove、onmouseup。
然后,如果你在它里面想获取各种各样的东西,有一点不太一样。
比如我们来弄个小例子:
那么这时候,当我们去触摸的时候,你可以看到,一个 TouchEvent 就出现了。
然后它里面也有一堆乱七八糟的东西,注意,像我们平常那些 X / Y 之类的东西,你可以看到在它里面都是没有的:
为什么呢?原因特别简单。
因为实际上来说,我们的 touch 它是允许多点的。
那么在允许多点的情况下,它给你的就不是一个坐标,而是一堆坐标了,是一个数组。
所以这时候,我们有一个东西,叫做 targetTouches,这个上面,就有我们所熟系的那些东西了:
你可以看到,它是一个 Touch 对象,这上面就有那些 X / Y 了,但是没有 offsetX / Y 的。
那么这时候第一个区别就出来了,它的坐标不是一个,而是一组。
然后它里边有个属性 radiusX / Y,这是什么东西呢?
现在我们先把这个 radiusX / Y 给打印出来:
首先,我直接告诉大家,radiusX / Y 这个东西不兼容。
然后你可以看到,无论我们在 div 里边点哪,它都是 11.5,就没变过。
实际上来说,radius 这个东西,我们见到它的情况下,一般都是在圆角那,所谓弧度的意思,但是我们这边无论点哪,它就没变过,并没有发挥任何弧度的一个优势。
其实它是这样的,它在我们单点触摸里面是没有意义的,我们到了多点的时候就要用它,那时候你就会发现它是会变的。
然后既然我们有了 clientX /Y 和 pageX / Y 之类的,那么我们就可以直接来用。
当然,因为我们现在是电脑上做测试的,只有一个点,所以我们现在只能看到一个值,但是这就够了:
然后 ontouchstart 之后,我们还可以再加一个 ontouchmove。
它跟我们鼠标的 onmousemove 也差不多,然后在它里面,我们也是要用 targetTouches 这个东西的:
那么你可以看到,当我按下去移动的时候,也可以跟踪这个值。
然后接下来,我们还有一个,ontouchend:
可以看到,当我按下去,再抬起的时候,挂了。
所以,在 ontouchend 的时候,是没有 targetTouches 的,实际上它是有另一个数组来供我们用,叫做 changeTouchs:
可以看到,它是一个 Touchlist,那么这个是怎么回事呢?
它是这样的,比方说在你手机屏幕上,不管谁先谁后,你有三个手指头摁下去了,接下来我抬起一个手指,这时候你就会触发一个 ontouchend。
注意,在这时候这个changeTouchs,它就是告诉你,你的那个手指变动,是怎么个变动法。比方说是哪个手指变了,1 还是 2 还是 3,它里面有这些东西。
接下来,我们就来看下怎么样去做它。
touch 这个事件,它最麻烦的其实还不是这几个东西怎么折腾的问题,它最麻烦的是兼容问题。
这个 touch 事件是我们所有高级浏览器里面,唯一的一个兼容问题最严重的一个玩意,它在各个手机上面都不太一样。
比如,别的先不说,就来一个最简单的事,让这个 div 它能拖动:
这应该是最简单的行为了,只是单点,不考虑多点。
那么现在如果我想它能拖的话,跟我们前面做的事其实是一样的。
首先,我们先给它加个 position:absolute。
然后这时候,我们需要先把 X / Y 搞出来。
因为是单点,所以我们只考虑第一个,也就是 ev.targetTouches[0]
接下来,我们就用 clientX / Y 来减掉 div 的 offsetLeft / Top。
为什么要用 clientX / Y?因为只有它可以用:
然后这两个有了之后,接下来就需要去算了。
首先,在 ontouchmove 里面,我们基本上做的事还是不变的,依然是让 div 的 left 和 top 来变:
而在 ontouchend 里面,因为我们现在主要用的是单个手指,所以在这个时候,ontouchend 里面其实是没发挥什么作用的。
如果是在多点的时候,你就需要移除相应的那个手指所对应的事件,事情就会变的有点麻烦。
然后现在你就可以看到这个东西可以拖动了:
但是拖动的过程当中,其实很多的事就来了。
比方说,我们最常见的一个问题就是,我们页面不是空空荡荡的,总是会有一些各种各样的文字:
所以在拖动的过程当中呢,实际上来说有很多问题。
第一,它有可能会把字选中,这个 chrom 模拟不出来,但是在某些特定的机种上会选中字。
第二,还有另外一个问题。
比如现在我让整个页面,也就是 body 有一个高:
我们知道,手指在屏幕上滑动,更多的其实是在拖页面本身。
那么这时候,我们在拖 div 的时候,你就会发现 div 在走,页面也跟着在滚动,这个就很乱套了:
所以这时候就有一个问题了,我希望的是,我拖这个 div 的时候,只是 div 本身的问题,页面不要跟着滚动。
这个其实就跟我们前面博客说的一个东西联系上了,就是说,我本身在页面上拖动手指,这个页面会动,这事是我搞的吗?
不是,是系统搞的。
那么是系统搞的,我们就可以干掉它。
那这时候就又有一个问题出现了。
现在至少涉及到三个事件 ontouchstart、ontouchmove、ontouchend,那我们应该在谁上面来阻止呢?
我们现在就先随便先一个,就 ontouchstart:
那么这时候你可以看到,在拖动的时候,目前就没问题了。
但是如果有做过的就会知道,在一部分的安卓手机上面,它这个页面还会滚动。
那么这个东西如果真的想解决的话,应该怎么办呢?
就需要我们在 ontouchmove 里面也阻止一下:
那么这时候,就没太大问题了。