likes
comments
collection
share

vue 使用hammerjs 完成图片的双指放大缩小及单指移动

作者站长头像
站长
· 阅读数 283
<template>
  <div class="page">
    <div class="demo">
      <img id="demoImg" :src="require('../../assets/newimages/code.png')" class="demo-img" />
    </div>
  </div>
</template>
<script>
import Hammer from 'hammerjs'
import { setTimeout } from 'timers'
export default {
  data () {
    return {
      config: {},
      id: null,
      mc: null,
      timer: false,
      translateX: 0,
      translateY: 0,
      scale: 1,
      firstTouch: true,
      relateX: 0,
      relateY: 0,
      oldX: 0,
      oldY: 0,
      oldScale: 1
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.picInit()
    })
  },
  methods: {
    picInit () {
      this.id = document.getElementById('demoImg')
      this.mc = new Hammer(this.id)
      this.relateX = (document.body.clientWidth - this.id.offsetWidth) / 2
      this.relateY = (document.body.clientHeight - this.id.offsetHeight) / 2

      this.mc.add(new Hammer.Pan({
        direction: Hammer.DIRECTION_ALL,
        threshold: 0,
        pointers: 0
      }))
      this.mc.add(new Hammer.Pinch({
        threshold: 0
      })).recognizeWith(this.mc.get('pan'))

      this.mc.on('hammer.input', this.isFinal)
      this.mc.on('panstart panmove', this.onPan)
      this.mc.on('pinchstart pinchmove', this.onPinch)

      this.setPosition()
    },
    isFinal (ev) {
      if (ev.isFinal) {
        this.oldX = this.translateX
        this.oldY = this.translateY
        this.oldScale = this.scale
      }
    },
    // 初始化图片位置及缩放
    setPosition () {
      this.selfPosition({
        translateX: this.relateX,
        translateY: this.relateY,
        scale: this.scale
      })
    },
    // 单点触发 - 拖拉
    onPan (ev) {
      // console.log(this.firstTouch)
      if (this.firstTouch) {
        this.oldX = this.relateX
        this.oldY = this.relateY
      }
      // console.log(this.oldX)
      // console.log(this.oldY)
      this.translateX = this.oldX + ev.deltaX
      this.translateY = this.oldY + ev.deltaY
      const position = {
        translateX: this.translateX,
        translateY: this.translateY,
        scale: this.scale
      }
      this.selfPosition(position)
      this.firstTouch = false
    },
    // 多点触发 - 缩放
    onPinch (ev) {
      this.scale = this.oldScale * ev.scale
      this.selfPosition({
        translateX: this.translateX,
        translateY: this.translateY,
        scale: this.scale
      })
      // this.selfPosition(this.position)
    },
    selfPosition (pos) {
      return this.picAnimate()(() => this.tempPos(pos))
    },
    tempPos (pos) {
      let style = [
        `translate3d(${pos.translateX}px, ${pos.translateY}px, 0)`,
        `scale(${pos.scale}, ${pos.scale})`
        // `scale(${pos.scale > 1.2 ? 1.2 : pos.scale}, ${pos.scale > 1.2 ? 1.2 : pos.scale})`
      ]
      style = style.join(' ')
      this.id.style.transform = style
    },
    picAnimate () {
      return window[Hammer.prefixed(window, 'requestAnimationFrame')] || function (callback) {
        setTimeout(callback, 1000 / 60)
      }
    }
  }
}
</script>
<style lang="less">
.page {
  width: 375px;
  height: 100vh;
  background: url('../../assets/newimages/bg.png') center center no-repeat;
  background-size: 100% 100%;
}
.demo {
  position: absolute;
}
.demo-img {
  width: 260px;
  height: 260px;
  display: block;
  overflow: hidden;
}
</style>