Vue2实现图片的拖拽,缩放和旋转效果的示例代码

 更新时间:2022年11月29日 10:44:27   作者:monkeyLi  
这篇文章主要为大家介绍了如何基于vue2 实现图片的拖拽、旋转、鼠标滚动放大缩小等功能。文中的示例代码讲解详细,感兴趣的小伙伴可以尝试一下

效果图

分步骤实现

在这里看下 拖拽、旋转、缩放的几个方法

1.获取图片的实际宽高

getImgSize(url) {
  return new Promise((resolve, reject) => {
    let imgObj = new Image();
    imgObj.src = url;
    imgObj.onload = () => {
      resolve({
        width: imgObj.width,
        height: imgObj.height,
      });
    };
  });
},

2.根据盒子的大小、图片的大小来计算 要显示多大的图片

 async initImage() {
      if (!this.imageUrl) {
        return;
      }
      let { width, height } = await this.getImgSize(this.imageUrl);
      // 设置原始图片的大小
      let realWidth = width;
      let realHeight = height;

      // 获取高宽比例
      const whRatio = realWidth / realHeight;
      const hwRatio = realHeight / realWidth;

      //获取盒子的大小
      const boxW = this.$refs.maskBox.clientWidth;
      const boxH = this.$refs.maskBox.clientHeight;

      if (realWidth >= realHeight) {
        this.imgH = hwRatio * boxW;
        const nih = this.imgH;
        if (nih > boxH) {
          this.imgH = boxH;
          this.imgW = whRatio * boxH;
        } else {
          this.imgW = boxW;
        }
        this.top = (boxH - this.imgH) / 2;
        this.left = (boxW - this.imgW) / 2;
      } else {
        this.imgW = (boxH / realHeight) * realWidth;
        this.imgH = boxH;
        this.left = (boxW - this.imgW) / 2;
      }
    },

在这里主要是根据图片的宽高 ,以及盒子的大小来计算 盒子中展示多大的图片,将图片按照比例缩放后展示到盒子中。

3.拖拽图片

主要是监听@mousedown事件

onmousedownHandle(e) {
  const that = this;
  this.$refs.maskBox.onmousemove = function (el) {
    const ev = el || window.event; // 阻止默认事件
    ev.preventDefault();
    that.left += ev.movementX;
    that.top += ev.movementY;
  };
  this.$refs.maskBox.onmouseup = function () {
    // 鼠标抬起时将操作区域的鼠标按下和抬起事件置为null 并初始化
    that.$refs.maskBox.onmousemove = null;
    that.$refs.maskBox.onmouseup = null;
  };
  if (e.preventDefault) {
    e.preventDefault();
  } else {
    return false;
  }
},

4. 旋转图片

handleRotate() {
  this.deg += 90;
  if (this.deg >= 360) {
    this.deg = 0;
  }
  this.size = 0;
  this.scale = `scale(1) rotateZ(${this.deg}deg)`;
},

5.监听鼠标的滚动,进行缩放图片

在 mounted() 中监听鼠标的滚动事件

mounted() {
    // 兼容火狐浏览器
    this.mousewheelevt = /Firefox/i.test(navigator.userAgent)? "DOMMouseScroll" : "mousewheel";
    // 为空间区域绑定鼠标滚轮事件 =》 处理函数是wheelHandle
    // 如果你监听了window的scroll或者touchmove事件,你应该把passive设置为true,这样滚动就会流畅很多
    this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle, {passive:true});
},

处理鼠标的滚动事件

wheelHandle(e) {
    // 兼容性处理 => 火狐浏览器判断滚轮的方向是属性 detail,谷歌和ie浏览器判断滚轮滚动的方向是属性 wheelDelta
    const ev = e || window.event;
    // dir = -dir; // dir > 0 => 表示的滚轮是向上滚动,否则是向下滚动 => 范围 (-120 ~ 120)
    const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;
    //滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例
    this.imgScaleHandle(dir / 2000);
},

放大缩小图片

/**
 * 图片的缩放
 * zoom >0 放大
 * zoom <0 缩小
 */
imgScaleHandle(zoom) {
    this.size += zoom;
    if (this.size < -0.5) {
        this.size = -0.5;
    }
    this.scale = `scale(${1 + this.size}) rotateZ(${this.deg}deg)`;
},

页面销毁的时候 注意要取消鼠标的监听事件

beforeDestroy() {
    //取消监听
    this.$refs.maskBox.removeEventListener(this.mousewheelevt,this.wheelHandle,{passive:true});
},

以上就是主要实现功能的方法

完整代码

<template>
  <div class="home">
    <div class="btn-area">
      <button @click="switchImgHandle(1)">竖图</button>
      <button @click="switchImgHandle(2)">横图</button>
      <button @click="handleRotate">旋转</button>
      <button @click="imgScaleHandle(0.25)">放大</button>
      <button @click="imgScaleHandle(-0.25)">缩小</button>
      <button @click="handleReset">重置</button>
    </div>
    <div class="image-box" ref="maskBox" @mousedown="onmousedownHandle">
      <img :src="imageUrl" alt="" :style="{width: imgW + 'px', height: imgH + 'px',
          top: top + 'px', left: left + 'px', transform: scale, }" />
    </div>
  </div>
</template>

<script>
export default {
  name: "HomeView",
  data() {
    return {
      imageUrl: "",
      imageUrl1: require("@/assets/img1.jpg"),
      imageUrl2: require("@/assets/img2.jpg"),
      imgW: 0,
      imgW: 0,
      imgH: 0,
      deg: 0,
      top: 0,
      left: 0,
      scale: "scale(1)",
      size: 0,
      mousewheelevt: null,
    };
  },
  mounted() {
    this.imageUrl = this.imageUrl1;
    //初始化图片
    this.initImage();

    // 兼容火狐浏览器
    this.mousewheelevt = /Firefox/i.test(navigator.userAgent) ? "DOMMouseScroll" :"mousewheel";
    // 为空间区域绑定鼠标滚轮事件 =》 处理函数是wheelHandle
    // 如果你监听了window的scroll或者touchmove事件,你应该把passive设置为true,这样滚动就会流畅很多
    this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle, { passive:true});
  },
  beforeDestroy() {
    //取消监听
    this.$refs.maskBox.removeEventListener(this.mousewheelevt,this.wheelHandle,{passive:true});
  },
  methods: {
    /**
     * 切换图片
     *  flag: 1竖图 2 横图
     */
    switchImgHandle(flag) {
      if (flag === 1) {
        this.imageUrl = this.imageUrl1;
      } else {
        this.imageUrl = this.imageUrl2;
      }
      this.handleReset();
    },
    /**
     * 获取图片的url
     * @param {string} url
     */
    getImgSize(url) {
      return new Promise((resolve, reject) => {
        let imgObj = new Image();
        imgObj.src = url;
        imgObj.onload = () => {
          resolve({
            width: imgObj.width,
            height: imgObj.height,
          });
        };
      });
    },
    /**
     * 初始化图片
     */
    async initImage() {
      if (!this.imageUrl) {
        return;
      }
      let { width, height } = await this.getImgSize(this.imageUrl);
      // 设置原始图片的大小
      let realWidth = width;
      let realHeight = height;

      // 获取高宽比例
      const whRatio = realWidth / realHeight;
      const hwRatio = realHeight / realWidth;

      //获取盒子的大小
      const boxW = this.$refs.maskBox.clientWidth;
      const boxH = this.$refs.maskBox.clientHeight;

      if (realWidth >= realHeight) {
        this.imgH = hwRatio * boxW;
        const nih = this.imgH;
        if (nih > boxH) {
          this.imgH = boxH;
          this.imgW = whRatio * boxH;
        } else {
          this.imgW = boxW;
        }
        this.top = (boxH - this.imgH) / 2;
        this.left = (boxW - this.imgW) / 2;
      } else {
        this.imgW = (boxH / realHeight) * realWidth;
        this.imgH = boxH;
        this.left = (boxW - this.imgW) / 2;
      }
    },
    /**
     * 旋转
     */
    handleRotate() {
      this.deg += 90;
      if (this.deg >= 360) {
        this.deg = 0;
      }
      this.size = 0;
      this.scale = `scale(1) rotateZ(${this.deg}deg)`;
    },

    /**
     * 图片的缩放
     *    zoom >0 放大
     *    zoom <0 缩小
     */
    imgScaleHandle(zoom) {
      this.size += zoom;
      if (this.size < -0.5) {
        this.size = -0.5;
      }
      this.scale = `scale(${1 + this.size}) rotateZ(${this.deg}deg)`;
    },

    /**
     * 重置
     */
    handleReset() {
      this.imgW = 0;
      this.imgH = 0;
      this.top = 0;
      this.left = 0;
      this.deg = 0;
      this.scale = "scale(1)";
      this.size = 0;
      this.initImage();
    },

    /**
     * 鼠标滚动 实现放大缩小
     */
    wheelHandle(e) {
      const ev = e || window.event; // 兼容性处理 => 火狐浏览器判断滚轮的方向是属性 detail,谷歌和ie浏览器判断滚轮滚动的方向是属性 wheelDelta
      // dir = -dir; // dir > 0 => 表示的滚轮是向上滚动,否则是向下滚动 => 范围 (-120 ~ 120)
      const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;
      //滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例
      this.imgScaleHandle(dir / 2000);
    },

    /**
     * 处理图片拖动
     */
    onmousedownHandle(e) {
      const that = this;
      this.$refs.maskBox.onmousemove = function (el) {
        const ev = el || window.event; // 阻止默认事件
        ev.preventDefault();
        that.left += ev.movementX;
        that.top += ev.movementY;
      };
      this.$refs.maskBox.onmouseup = function () {
        // 鼠标抬起时将操作区域的鼠标按下和抬起事件置为null 并初始化
        that.$refs.maskBox.onmousemove = null;
        that.$refs.maskBox.onmouseup = null;
      };
      if (e.preventDefault) {
        e.preventDefault();
      } else {
        return false;
      }
    },
  },
};
</script>

<style scoped>
.home {
  width: 1000px;
  margin: 50px auto;
}
.btn-area {
  display: flex;
  justify-content: center;
  width: 100%;
  margin-bottom: 50px;
}
.btn-area button {
  width: 100px;
  height: 40px;
  font-size: 18px;
  margin-right: 10px;
}
.image-box {
  position: relative;
  margin: 0 auto;
  width: 1000px;
  height: 700px;
  border: 1px solid #333;
  overflow: hidden;
}
.image-box img {
  position: absolute;
  cursor: pointer;
}
</style>

以上就是Vue2实现图片的拖拽,缩放和旋转效果的示例代码的详细内容,更多关于Vue图片拖拽 缩放 旋转的资料请关注脚本之家其它相关文章!

相关文章

  • vue实现防抖的实例代码

    vue实现防抖的实例代码

    这篇文章主要给大家介绍了关于vue实现防抖的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Vue使用NProgress的操作过程解析

    Vue使用NProgress的操作过程解析

    这篇文章主要介绍了Vue使用NProgress的操作过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • JavaScript实现简单的图片切换功能(实例代码)

    JavaScript实现简单的图片切换功能(实例代码)

    这篇文章主要介绍了JavaScript实现简单的图片切换功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-04-04
  • vue打包时不删除dist里的原有文件配置方法

    vue打包时不删除dist里的原有文件配置方法

    这篇文章主要为大家介绍了vue打包时不删除dist里的原有文件配置方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Vue3实现组件级基类的多种方法

    Vue3实现组件级基类的多种方法

    vue3提供了 mixins和extends,但是尝试之后发现这两种方法只支持纯OptionAPI,设置的data会被识别,但是设置的setup里return 的 reactive,完全无效,setup也没有被执行,这篇文章主要介绍了Vue3实现组件级基类的几种方法,需要的朋友可以参考下
    2023-04-04
  • vue中为什么在组件内部data是一个函数而不是一个对象

    vue中为什么在组件内部data是一个函数而不是一个对象

    这篇文章主要介绍了vue中为什么在组件内部data是一个函数而不是一个对象,本文通过示例代码给大家讲解的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • 聊聊Vue 中 title 的动态修改问题

    聊聊Vue 中 title 的动态修改问题

    这篇文章主要介绍了 Vue 中 title 的动态修改问题,文中通过两种方案给大家介绍了title的传递问题 ,需要的朋友可以参考下
    2019-06-06
  • 说说如何在Vue.js中实现数字输入组件的方法

    说说如何在Vue.js中实现数字输入组件的方法

    这篇文章主要介绍了说说如何在Vue.js中实现数字输入组件的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Vue Echarts实现多功能图表绘制的示例详解

    Vue Echarts实现多功能图表绘制的示例详解

    作为前端人员,日常图表、报表、地图的接触可谓相当频繁,今天小编隆重退出前端框架之VUE结合百度echart实现中国地图+各种图表的展示与使用;作为“你值得拥有”专栏阶段性末篇,值得一看
    2023-02-02
  • vue+Element实现搜索关键字高亮功能

    vue+Element实现搜索关键字高亮功能

    这篇文章主要为大家详细介绍了vue+Element实现搜索关键字高亮功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05

最新评论