vue 项目中实现图片滚轮缩放,鼠标拖拽功能(类似操作百度地图方式)
...大约 2 分钟
vue 项目中实现图片滚轮缩放,鼠标拖拽功能(类似操作百度地图方式)
背景
项目中需要查看一个零件图,需要实现图片的滚轮缩放,鼠标拖拽功能,类似百度地图的拖拽和缩放功能,实现方式如下:
1、父组件
<template>
  <div class="box">
    <ImageView ref="ImageViewRef" :imageUrl="url" />
    <button class="btn-box" @click="reset">重置</button>
  </div>
</template>
<script>
import ImageView from './ImageViewr.vue'
export default {
  components: {
    ImageView
  },
  data() {
    return {
      url: 'https://ts1.tc.mm.bing.net/th?id=ORMS.EBNm8u94OA0h0A&w=612&h=304&qlt=90&c=1&rs=1&dpr=1.5&p=0'
    }
  },
  methods: {
    reset() {
      this.$refs.ImageViewRef.resetImage()
    }
  }
}
</script>
<style lang="scss" scoped>
.box {
  width: 500px;
  height: 400px;
  border: 1px solid red;
  .btn-box {
    position: absolute;
    top: 320px;
  }
}
</style>2、子组件
<template>
  <div class="imageView" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseleave="onMouseUp" @mouseup="onMouseUp">
    <img :src="imageUrl" ref="image" @wheel="onWheel" />
  </div>
</template>
<script>
export default {
  props: {
    imageUrl: {
      type: String,
      require: true,
      default: ''
    }
  },
  data() {
    return {
      currentScale: 1, // 当前缩放比例
      isDragging: false, // 是否正在拖拽图片
      startX: 0, // 拖拽起始点x坐标
      startY: 0, // 拖拽起始点y坐标
      translateX: 0, // 图片平移x方向距离
      translateY: 0, // 图片平移y方向距离
      dragSpeed: 0.3, // 拖拽速度
      zoomSpeed: 0.1, // 控制缩放速度
      maxScale: 5, // 最大缩放值
      minScale: 0.1 // 最小缩放值
    }
  },
  methods: {
    // 鼠标按下事件处理函数
    onMouseDown(e) {
      e.preventDefault()
      this.isDragging = true
      this.startX = e.clientX
      this.startY = e.clientY
      this.$refs.image.style.cursor = 'grabbing'
    },
    // 鼠标移动事件处理函数
    onMouseMove(e) {
      if (!this.isDragging) return
      const deltaX = (e.clientX - this.startX) * this.dragSpeed
      const deltaY = (e.clientY - this.startY) * this.dragSpeed
      this.translateX += deltaX
      this.translateY += deltaY
      this.$refs.image.style.transform = `scale(${this.currentScale}) translate(${this.translateX}px, ${this.translateY}px)`
      this.startX = e.clientX
      this.startY = e.clientY
    },
    // 鼠标松开事件处理函数
    onMouseUp() {
      this.isDragging = false
      this.$refs.image.style.cursor = 'grab'
    },
    // 鼠标滚轮事件处理函数
    onWheel(e) {
      e.preventDefault()
      const delta = e.deltaY > 0 ? -1 : 1
      this.currentScale = Math.min(this.maxScale, Math.max(this.minScale, this.currentScale + delta * this.zoomSpeed))
      this.$refs.image.style.transform = `scale(${this.currentScale}) translate(${this.translateX}px, ${this.translateY}px)`
    },
    // 重置图片缩放和移动
    resetImage() {
      this.currentScale = 1
      this.translateX = 0
      this.translateY = 0
      this.$refs.image.style.transform = 'scale(1) translate(0, 0)'
    }
  }
}
</script>
<style lang="scss" scoped>
.imageView {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.imageView .elImageclass {
  width: 100%;
  height: 100%;
  touch-action: none;
  user-drag: none;
  -webkit-user-drag: none;
}
img {
  width: 100%;
  height: 100%;
  cursor: grab;
  object-fit: contain !important;
}
</style>