在移动端用 Touch 事件以拖拽手指实现伪 hover

2015-11-02

然后有一个非常简单的方式实现

在需要的元素或者整个 body & html 根上绑定 touchstart 事件。放弃以下的蹩脚方法!

—-

前言:

  我们知道触屏设备,移动端浏览器它没有 hover 的动作效果,其次我们知道 iOS 的 Safari 与 Chrome 是不会对 hover 做出反馈的(它会在手指点击的时候瞬间执行一次 hover 效果,但随即便进入 a 标签的超链接,而假设不为 a 标签则就完全不会显示 CSS 中设定的 hover 效果),而 Android 系统下则会将触摸判断为 hover 并显示,但是它有一个严重的问题,即是 hover 状态会一直停留不取消,当我们不停的挪动手指触摸到不同位置将会看到一个非常糟糕的体验。(iOS 下的 Opera 和 搜狗 等浏览器的默认设定与 Safari 和 Chrome 不同,它的默认设定和 Android 相同)。

  以上便是这篇文章所要解决的问题,我们需要一个 hover 效果,与此同时不同的移动端浏览器或不同系统下的,使它们达到相同的交互显示效果。

正文:

  我们要实现一个怎样的 hover 效果?

  在这里的显示效果是这样的,这里的陈述将根据 iOS Safari 为基础:当我们的手指触摸到某个需要 hover 的元素,它将展示 hover 的效果(通常情况下如果触摸为点击而非拖拽挪动手指,则会直接触发 a 标签的超链接,而当我们点触的同时并挪动手指,则 a 标记的超链接则不会触发),那么我们要利用的便是这种状况,利用挪动,或者非 a 标签直接实现 hover。接着当手指松开的时候 hover 效果取消。


【触摸模块时 hover】

IMG_0636
【松开手指时 取消 hover】

  注意上面这个结果,无论在 iOS 或是 Android 它们的效果是相同的,同时“稍后观看”按是 :hover 而非我们制造的 .hover 所以 它会停留住,即便你松开了手指(因为在这里我们需要这个按钮在 hover 之后可点击),图中第1个和第3个模块是没有任何操作情况下的常态。这样就达到了一个复杂的效果。

  我们知道 js 无法直接操作 css 中的 :hover 写法,那么显然,没错,我们要自动的为触摸到的元素添加 class 使用 .hover 来塑造一个 :hover 效果。而以下我们将介绍两种情况下做这件事的方案。

  首先第一种情况,是一个完整的全新的设计时可以用的:

  此时发生的事情和 CSS 需要相应做的事是:body 中的任意标签 在 hover 与 拖拽时均会给该元素添加一个 .hover class,所以我们的 CSS 当中,将用 .hover 完全的取代 :hover(:active :focus 等保持原本写法),如此一来无论桌面系统的鼠标 hover 还是触摸时 hover 的表现结果是相同的这点不用担心。上面的代码我们分别定义了 touch 事件的 触摸 拖拽 为 添加 class,而结束时 删掉这个 class。

  第二种情况是你的项目已经开发到了比较完善的程度,此时无法完全的使用 .hover 取代 :hover(其实改改应该也不难),又或者你只希望这种动作只发生在某些特别的位置:

  以上的代码将 body * 选择器写成了 class(这是你需要指定的位置),当然的你可以指定多个 class,不同之处在于,因为你的 CSS 本身已经设定了 :hover 代码,这个时候当你将 :hover 需要效果的部分同时增加上 .hover 会造成两种同时存在的结果。所以我们需要每一个动作都有一个反向的 .no_hover,同时你需要对 .no_hover 添加上反向的 CSS 代码(即未触发 hover 时的样式 还原回效果)。

  我推荐第一种方法,但它的开销可能大一些,每次 hover 都会对 dom 进行操作,因为第二种方法需要写的 CSS 内容会多很多,但如果只是很局部的使用则第二种比较好。推荐第一种的原因在于,如果浏览器的默认设定得到了改善,到时候你只需要批量的将 CSS 中的 .hover 字样替换成 :hover 一切就会恢复成通常的方式了。

  这是非常值得尝试的一种效果,它让 Web 在触屏设备上拥有了如同 APP 一样的交互效果,不要小看它,虽然代码并不复杂,要知道越是基础的东西,越是看似简单的东西,越为重要,比起复杂炫酷的特效,我们在屏幕上操作最多的这种基本动作反而更影响体验,着显细节。

末尾:

  你恐怕要着一段代码阻止移动设备长按浏览器而弹出的菜单,这是必须的,iOS 下的代码很简单,只有一段 CSS 就可以做到,而 Android 要麻烦一些(我暂时没有找到方法 过往的 js 似乎对 Android 5.x 的 Chrome 就不起效)。如果你有对安卓的方法,请多指教。