基于vue实现图片的拖拽和缩放

2,328 阅读1分钟

一、组件代码:

<template>
  <div ref="maskBox" class="bigImgBox" @mousedown="onmousedown">
    <img
      :src="srcPath"
      alt="加载失败"
      :style="{'width': imgW + 'px','height': imgH + 'px','top': top + 'px', 'left': left + 'px', 'transform': scale}">
    // 用来放置源图片
    <img v-show="false" ref="resource" :src="srcPath" alt="">
  </div>
</template>
<script>
export default {
  props: ['srcPath'],
  data() {
    return {
      imgW: 0,
      imgH: 0,
      top: 0,
      left: 0,
      src: '',
      reW: 0, // 原图
      reH: 0,
      scale: 'scale(1)',
      size: 0
    }
  },
  mounted() {
    // 设置原始图片的大小
    this.reW = this.imgW = this.$refs.resource.width
    this.reH = this.imgH = this.$refs.resource.height
    // 获取宽高比例
    const whRatio = this.reW / this.reH
    // 获取高宽比例
    const hwRatio = this.reH / this.reW
    const bodyW = document.body.clientWidth
    const bodyH = document.body.clientHeight
    console.log(this.reW, this.reH, bodyW, bodyH)
    // 图片宽度大于高度
    if (this.reW >= this.reH) {
      const nih = this.imgH = hwRatio * bodyW
      if (nih > bodyH) {
        this.imgH = bodyH
        this.imgW = whRatio * bodyH
        this.left = (bodyW - whRatio * bodyH) / 2
      } else {
        this.imgW = bodyW
        this.top = (bodyH - nih) / 2
      }
    } else {
      const niw = this.imgW = (bodyH / this.reH) * this.reW
      this.imgH = bodyH
      this.left = (bodyW - niw) / 2
    }
    // 兼容火狐浏览器
    const mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? 'DOMMouseScroll' : 'mousewheel' 
    // FF doesn't recognize mousewheel as of FF3.x
    // 为空间区域绑定鼠标滚轮事件 =》 处理函数是mWheel
    this.$refs.maskBox.addEventListener(mousewheelevt, this.mWheel, false)
  },
  methods: {
    hideMask(e) {
      // 控制缩放的图片显示和隐藏(本质是组件的显示和隐藏) => 图片的位置在父组件中
      this.$emit('clickMask', false)
    },
    mWheel(e) {
      const ev = e || window.event
      // 兼容性处理 => 火狐浏览器判断滚轮的方向是属性 detail,谷歌和ie浏览器判断滚轮滚动的方向是属性 wheelDelta
      const dir = ev.detail ? ev.detail * (-120) : ev.wheelDelta
      // dir = -dir;
      // dir > 0 => 表示的滚轮是向上滚动,否则是向下滚动 => 范围 (-120 ~ 120)
      if (dir > 0) {
        //  > 0 => 表示向上滚动,为正值;滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例
        this.size += dir / 2000
        // scale 图片缩放比例
        this.scale = `scale(${1 + this.size})`
      } else {
        // < 0 => 表示向下滚动,为负值;滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例
        this.size += dir / 2000
        if (this.size < -1) {
          this.size = -1
          this.scale = `scale(${1 + this.size})`
          return
        }
        this.scale = `scale(${1 + this.size})`
      }
    },
    // 图片拖动处理函数
    onmousedown(e) {
      const that = this
      let isMove5 = false
      // 为操作区域绑定鼠标 放下和抬起事件
      this.$refs.maskBox.onmousemove = function(el) {
        const ev = el || window.event
        // 阻止默认事件
        ev.preventDefault()
        if (Math.abs(ev.movementX) > 5 || Math.abs(ev.movementY) > 5) {
          isMove5 = true
        }
        that.left += ev.movementX
        that.top += ev.movementY
      }
      this.$refs.maskBox.onmouseup = function() {
        // 不兼容IE => 判断浏览器是IE,就不渲染操作区域
        if (that.isIE() || that.isIE11()) {
          that.hideMask()
        }
        // 鼠标抬起时将操作区域的鼠标按下和抬起事件置为null 并初始化
        that.$refs.maskBox.onmousemove = null
        that.$refs.maskBox.onmouseup = null
        if (!isMove5) {
          that.hideMask()
        }
      }
      // 阻止默认是按发生
      if (e.preventDefault) {
        e.preventDefault()
      } else {
        return false
      }
    },
    isIE() {
      if (!!window.ActiveXObject || 'ActiveXObject' in window) {
        return true
      } else {
        return false
      }
    },
    isIE11() {
      if ((/Trident\/7\./).test(navigator.userAgent)) {
        return true
      } else {
        return false
      }
    }
  }
}
</script>
<style>
.bigImgBox {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 9000;
    background-color: rgba(0, 0, 0, .6)
}
.bigImgBox img {
    position: fixed;
    z-index: 9001;
}
</style>

二、组件使用

<!-- 需要require引入图片 -->
<div class="helloBox" @click="showBigImage(require('./common/earth.jpg'))" />
<pre-view v-if="isShow" :src-path="url" @clickMask="isShow = false" />
// 数据
data(){
    return {
      url: '',
      isShow: false,
    }
}
// 方法
showBigImage(url) {
   if (url) {
      this.url = url
      this.isShow = true
   }
},

三、学习思路

原文:blog.csdn.net/hbjiankely/…