Vue 加 Hammer 处理手势

2020-01-27

接近原生 App 体验,手势是少不了的。但是无论是 Vue 还是 Vuetify 对手势的支持并不好,于是需要 Hammer.js 支持。

 

Hammer.js #

hammerjs 在拙劣的搜索之后,才发现了这个库。虽然有 一个 Vue 的封装库 vue-touch,但是它年久失修,而且其组件名称v-touch与 Vuetify 的某组件重名。。。

使用 #

http://hammerjs.github.io/

文档非常简单,提几点需要注意的地方

Vue 引用 DOM 元素 #

配合$ref食用更佳

<template>
  <div ref="container">
  </div>
</template>

<script>
export default {
  mounted() {
    let ele = this.$refs.container
  }
}
</script>
Vue

做主人 #

通过new Hammer(myElement, myOptions)创建的事件监听默认开启了tap, doubletap, press, horizontal panswipe,并且加上了禁用了的pinchrotate

所以使用new Hammer.Manager(myElement, myOptions)更加舒服。

理解get #

为什么用Hammer创建的对象可以随便get然后设置enable: false,而Hammer.Manager出来是null呢?

如上所述,Hammer创建的默认加上了全套事件监听,而Hammer.Manager出来是白板一块,自然不能get没有加入的事件了。

大坑一个 #

文档里的确说了pinchrotate会阻塞元素的事件响应,但没想到有点愚蠢和暴力:启用了pinch之后,scroll就不行了?!一个手指的滑动和两个手指的缩放有关系?

还好找到了解决方案:https://stackoverflow.com/a/27550784/8810271

由于hammerjs2.x 版本不允许绑定touchstart and touchend,可以直接绑 DOM 元素上啊!

于是解决如下:

<template>
  <div ref="container" class="container" @touchstart="touchStart" @touchend="touchEnd">
  </div>
</template>

<script>
import Hammer from 'hammerjs'
let originZoom
export default {
  mounted() {
    hammer = new Hammer.Manager(this.$refs.container)
    hammer.add(new Hammer.Swipe({ direction: Hammer.DIRECTION_HORIZONTAL }))
    hammer.add(new Hammer.Pinch({ enable: false }))
    hammer.on('pinchstart', this.pinchStart)
    hammer.on('pinchmove', this.pinchMove)
  },
  methods: {
    pinchStart(e) {
      originZoom = this.zoom
    },
    pinchMove(e) {
      this.zoom = originZoom * e.scale
    },
    touchStart(e) {
      if (e.touches.length > 1) {
        hammer.get('pinch').set({ enable: true })
      }
    },
    touchEnd(e) {
      hammer.get('pinch').set({ enable: false })
    }
  }
}
</script>
Vue
Leave your comments and reactions on GitHub