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 dev server理解vite原理

    尤雨溪开发vue dev server理解vite原理

    这篇文章主要为大家介绍了尤雨溪开发的玩具vite,vue-dev-server来理解vite原理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • vue项目中锚点定位替代方式

    vue项目中锚点定位替代方式

    今天小编就为大家分享一篇vue项目中锚点定位替代方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vant自定义二级菜单操作

    vant自定义二级菜单操作

    这篇文章主要介绍了vant自定义二级菜单操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • vue vite之LogicFlow安装核心依赖及项目初始化详解

    vue vite之LogicFlow安装核心依赖及项目初始化详解

    这篇文章主要为大家介绍了vue vite之LogicFlow安装核心依赖及项目初始化详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • vue项目如何分环境部署

    vue项目如何分环境部署

    这篇文章主要介绍了vue项目如何分环境部署问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2018-12-12
  • vue-draggable实现拖拽表单的示例代码

    vue-draggable实现拖拽表单的示例代码

    本文主要介绍了vue-draggable实现拖拽表单的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • vue实现动态路由添加功能的简单方法(无废话版本)

    vue实现动态路由添加功能的简单方法(无废话版本)

    ue动态路由(约定路由),听起来好像很玄乎的样子,但是你要是理解了实现思路,你会发现没有想象中的那么难,下面这篇文章主要给大家介绍了关于vue实现动态路由添加功能的简单方法,需要的朋友可以参考下
    2023-02-02
  • vue前端实现表格数据增查改删功能

    vue前端实现表格数据增查改删功能

    增删改查是我们写项目百分之七十会遇到的代码,下面这篇文章主要给大家介绍了关于vue前端实现表格数据增查改删功能的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-05-05
  • 浅谈关于iview表单验证的问题

    浅谈关于iview表单验证的问题

    这篇文章主要介绍了浅谈关于iview表单验证的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • vue3+el-select实现触底加载更多功能(ts版)

    vue3+el-select实现触底加载更多功能(ts版)

    这篇文章主要给大家介绍了基于vue3和el-select实现触底加载更多功能,文中有详细的代码示例,感兴趣的同学可以借鉴参考下
    2023-07-07

最新评论