基本介绍
简介 : 这个插件主要用于判断用户的操作方式,究竟是用鼠标操作还是触屏操作,在引入了这个插件之后,当用户使用鼠标进行操作时 <html>
上将会出现 xj-operate-mouse
的类,当用户使用触屏进行操作时 <html>
上将会出现 xj-operate-touch
的类,这两个类名的设置并非是一次性的,它会根据用户的操作模式进行动态监听和变化,这有助于我们根据用户不同的操作方式进行不同的设置。
兼容 : IE10+ / Edge12+ / Firefox / Chrome / Safari / Opera / IOS Webkit / Android Platform
更新 : https://github.com/xjZone/xj.operate/blob/master/upgrade.md
源码 : https://github.com/xjZone/xj.operate/
协议 : Apache License 2.0
版本 :
引入插件
首先是引入相关的文件,推荐使用带 immutable 的 JSDelivr CDN:
如何使用
如果使用了鼠标进行操作,那么 html
标签会被添加 xj-operate-mouse
类名,如果使用了触屏进行操作,那么 html
标签会被添加 xj-operate-touch
类名,如果既不是鼠标也不是触屏,那么 html
标签会被添加 xj-operate-other
类名,但除非是手动调用了 xj.operate.otherSet()
方法,否则 other
状态一般都不会自动出现的,下面是一个简单的例子,什么状态就显示什么关键词:
让 hover 在触屏时无效
:hover
伪类选择器用于定义元素被鼠标悬停时的样式,但它在 touch 触屏操作的环境下表现就不是那么让人满意了,主要是触屏操作并不像鼠标那样有所谓的悬停状态,所以得点击后才能生效,它也没有像鼠标挪开这样的概念,所以得等到元素失焦后才会失效,这就造成了有时样式并不符合预期结果的情况,因此有人会希望触屏操作时不要让这个选择器生效,现在借助 xj.operate 插件可轻松实现了。
通过配置控制长按结果
在上个例子中我们已经展示了如何让 :hover
选择器不在触屏操作时生效,但如果你觉得在触屏操作时完全禁止 :hover
的样式有些不妥,那么也许可以考虑使用插件提供的折中方案,那就是通过全局配置中的 pressHover
参数,来允许触屏模式下让长按操作能响应 :hover
选择器,其工作原理是判断到长按就临时切换为鼠标的状态,之后如果再次触发了 touchstart
事件就恢复为触屏的状态。
通过配置自定义类名
如果你觉得插件提供的默认类名如 xj-operate-mouse
或 xj-operate-touch
实在是太长了,那么可通过全局配置进行修改,但实际上 XJ 并不推荐修改默认类名,因为 XJ 系列插件都是只响应这些默认类名而已,如果修改了可能会引发一些样式错误,但我们还是可以通过全局配置的 mouseCallback
, touchCallback
, otherCallback
这三个回调方法,在状态被改变的时候同时进行类名的设置。
手动调整当前状态
插件对象提供了 xj.operate.mouseSet()
, xj.operate.touchSet()
, xj.operate.otherSet()
这三个方法,用于手动改变当前的状态,但是这些改变都是暂时的,在调用了这些方法之后,一旦再次触发 mousemove
事件或者 touchstart
事件,就会恢复为原本的自然状态,除非是在调用这三个方法时传入 false
参数,那样就不会自动恢复了,更多细节可以参考之后的 xj.operate
对象。
xj.operate 对象
xj.operate
对象除了 mouseSet()
, touchSet()
, otherSet()
这三个方法之外,还有其他一些属性,下面都罗列一下,值得注意的是三个改变状态的方法,改变默认都是暂时性的,之后用户再次触发相关事件,将恢复为正常状态,除非是调用它们时传入 false
参数,此时如果不再重新调用一次 mouseSet()
或 touchSet()
或 otherSet()
,则不会再自动恢复监听,也就是说状态将固化。
全局配置
全局配置的对象,用于控制节点类名的设置,长按操作和时间间隔,状态被改变时的回调等内容,需要注意的是,全局配置得在引入插件前就设置好,否则插件加载并执行的时候找不到配置,就会认为配置不存在,并且版本号还要对得上,否则插件也不会理会的,例如本页面使用的插件是 0.6.0 的版本,在 xj.operateConfig
对象后面跟着的就是 ['0.6.0']
,版本匹配是考虑到多版本并存而设计的。
判断原理
如何判断当前是使用鼠标操作还是触屏操作?有些开发者会以浏览器是否支持 touchstart
事件做为依据,支持就认为是使用了触屏操作,然而这种判断方法并不可靠,因为支持该事件的设备,也可能是使用着鼠标进行操作的,使用鼠标的环境下设备也可能是支持触屏操作的,那么怎么做才更加准确呢?浏览器目前并没有提供任何关于用户操作模式的 API,但是我们可以曲折的实现,以下是判断的原理。
在支持触屏的环境下,常规的触屏点击会按顺序先触发 touchstart
再触发 mousemove
,所以我们可以使用这两个事件的时间间隔来进行判断,如果 touchstart
和 mousemove
的触发时间间隔大于 500ms
,那就认为这两个事件并非是同个点击操作导致的,所以此时是使用了鼠标,如果这两个事件的触发时间间隔小于 500ms
,则认为它们是由于触屏点击而同时触发的,那么此时是使用了触屏。
之所以使用 500
毫秒进行判断,是因为在部分移动端的浏览器如 Safari(IOS) 中,点击相关的事件存在 300 毫秒的延迟,而事件如果延迟 500
毫秒以上就是长按而不是点击了,所以小于 500
毫秒是比较适中的,兼顾到了延迟和长按,当然实际上判断操作还要考虑事件的真实性(event.isTrusted
)和滚动或捏合缩放等,但这些都是插件的细节,就不过多讲述了,有兴趣的可自行查看插件源码。
项目备注
01. :hover
和 :active
这两个伪类选择器在 Safari(IOS) 中存在问题,具体来讲就是如果目标节点无法被聚焦或点击时没有特殊效果,那么这个节点就无法正常响应这两个伪类选择器,解决这问题的常用手段有两种,一是给目标节点绑定 touchstart
事件,回调是个空函数也无所谓,二是给目标节点设置 tabIndex
属性,让节点变得可被聚焦,在之前 "让 hover 在触屏时无效" 的案例中,我们就采用了第二种方法来确保 :hover
伪类生效,但这个问题并不会出现在 button
和 a
这些本来就可聚焦或可点击的元素上。
02. 插件判断设备类型其实是动态的,因为存在触屏设备插上鼠标变成鼠标操控,或 PC 转为触屏模式如 Chrome 使用移动端模拟,所以动态监听下适应性会更好,但状态的改变还得等对应的事件被触发,也就是说改变并不是立刻生效的,起码得移动过鼠标或触屏过才行。
03. 有疑问或者发现 BUG,可到 GitHub 提 Issue,如果觉得插件写得还行,在 GitHub 中为本项目点个 ★Star 吧,感谢啦 ಠ‿ಠ ❤。
推荐阅读
XJ.Chen - 浅谈 :hover 伪类选择器在 touch 环境如何禁止生效的问题