[web教学] vue项目实现图片缩放与拖拽功能

[复制链接]
查看650 | 回复0 | 2023-8-23 11:52:29 | 显示全部楼层 |阅读模式 来自 中国北京
在项目开发中遇到一个需求:

   1:用鼠标滚轮可对图片举行缩放处理处罚
   2:点击按钮可对图片举行缩放处理处罚
   3:可对图片举行拖拽处理处罚
  
  我在开发中通过本身实现与百度检察良好的铁子举行了两种范例的利用
  
  1:个人举行实现:

  
  源码:
  1. <template>
  2.     <div class="pictureDetails">
  3.         <div class="pictureDetails-box">
  4.             <!-- 图片区 -->
  5.             <div class="box-img">
  6.                 <div style="width: 100%" class="left" @mousewheel.prevent="rollImg">
  7.                     <img :src="imgSrc" class="img" ref="imgDiv" :style="{ transform: 'scale(' + zoomD + ')' }"
  8.                         @mousedown="move" />
  9.                 </div>
  10.                 <!-- 按钮 -->
  11.                 <div class="Button-area">
  12.                     <ol>
  13.                         <li @click="zoomMax">
  14.                             大
  15.                         </li>
  16.                         <li @click="zoomMin">
  17.                             小
  18.                         </li>
  19.                         <li v-if="love" @click="btnLoveFlage">
  20.                             未赞
  21.                         </li>
  22.                         <li v-else @click="btnLoveFlage">
  23.                             已赞
  24.                             <!-- <img src="@/assets/images/pictureDetails/Collection.png" alt="点赞icon"> -->
  25.                         </li>
  26.                         <li @click="downloadImg(imgSrc, '哇哈哈')
  27.                         ">
  28.                             下载
  29.                         </li>
  30.                     </ol>
  31.                 </div>
  32.             </div>
  33.         </div>
  34.     </div>
  35. </template>
  36. <script>
  37. export default {
  38.     data() {
  39.         return {
  40.             zoomD: 1,
  41.             love: false,
  42.             imgSrc: 'https://img2.baidu.com/it/u=1395980100,2999837177&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=675',  //横图
  43.             // imgSrc: 'https://img1.baidu.com/it/u=1518057857,2376515959&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1675530000&t=d847d2430e87d04936f7d07f38cf60c5',  //竖图
  44.         }
  45.     },
  46.     created() {
  47.         //根据接口判断当前详情是否已经收藏
  48.         this.love = true;
  49.     },
  50.     mounted() {
  51.     },
  52.     methods: {
  53.         //移动demo
  54.         move(e) {
  55.             e.preventDefault();
  56.             // 获取元素
  57.             var personBox = document.querySelector(".left");
  58.             var img = document.querySelector(".img");
  59.             var x = e.pageX - img.offsetLeft;
  60.             var y = e.pageY - img.offsetTop;
  61.             // 添加鼠标移动事件
  62.             personBox.addEventListener("mousemove", move);
  63.             function move(e) {
  64.                 img.style.left = e.pageX - x + "px";
  65.                 img.style.top = e.pageY - y + "px";
  66.             }
  67.             // 添加鼠标抬起事件,鼠标抬起,将事件移除
  68.             img.addEventListener("mouseup", function () {
  69.                 personBox.removeEventListener("mousemove", move);
  70.             });
  71.             // 鼠标离开父级元素,把事件移除
  72.             personBox.addEventListener("mouseout", function () {
  73.                 personBox.removeEventListener("mousemove", move);
  74.             });
  75.         },
  76.         // 缩放图片
  77.         rollImg(e) {
  78.             let direction = e.deltaY > 0 ? 'down' : 'up'
  79.             if (direction === 'up') {
  80.                 // 滑轮向上滚动
  81.                 this.large();
  82.             } else {
  83.                 // 滑轮向下滚动
  84.                 this.Small();
  85.             }
  86.         },
  87.         //缩小按钮方法
  88.         zoomMin() {
  89.             this.Small();
  90.         },
  91.         //放大按钮方法
  92.         zoomMax() {
  93.             this.large();
  94.         },
  95.         //大
  96.         large() {
  97.             this.$nextTick(() => {
  98.                 if (this.zoomD < 6) {
  99.                     this.zoomD += 0.10
  100.                 }
  101.                 document.querySelector('.img').style.transform = `matrix(${this.zoomD}, 0, 0,${this.zoomD}, 0, 0)`
  102.             })
  103.         },
  104.         // 小
  105.         Small() {
  106.             this.$nextTick(() => {
  107.                 if (this.zoomD > 0.3) {
  108.                     this.zoomD -= 0.10
  109.                 }
  110.                 document.querySelector('.img').style.transform = `matrix(${this.zoomD}, 0, 0, ${this.zoomD}, 0, 0)`
  111.             })
  112.         },
  113.         //点击下载图片
  114.         downloadImg(url, name) {
  115.             let image = new Image();
  116.             image.setAttribute("crossOrigin", "anonymous");
  117.             image.src = url;
  118.             image.onload = () => {
  119.                 let canvas = document.createElement("canvas");
  120.                 canvas.width = image.width;
  121.                 canvas.height = image.height;
  122.                 let ctx = canvas.getContext("2d");
  123.                 ctx.drawImage(image, 0, 0, image.width, image.height);
  124.                 canvas.toBlob((blob) => {
  125.                     let url = URL.createObjectURL(blob);
  126.                     this.download(url, name);
  127.                     // 用完释放URL对象
  128.                     URL.revokeObjectURL(url);
  129.                 });
  130.             };
  131.         },
  132.         download(href, name) {
  133.             let eleLink = document.createElement("a");
  134.             eleLink.download = name;
  135.             eleLink.href = href;
  136.             eleLink.click();
  137.             eleLink.remove();
  138.         },
  139.         //点赞收藏
  140.         btnLoveFlage() {
  141.             this.love = this.love == true ? false : true;
  142.             console.log(this.love);
  143.         }
  144.     }
  145. }
  146. </script>
  147. <style lang="scss" scoped>
  148. .pictureDetails {
  149.     width: 100%;
  150.     height: auto;
  151.     background-color: #F3F1EE;
  152.     display: flex;
  153.     align-items: center;
  154.     flex-direction: column;
  155.     justify-content: center;
  156.     .pictureDetails-box {
  157.         width: 1200px;
  158.         // height: 800px;
  159.         display: flex;
  160.         flex-direction: column;
  161.         .box-img {
  162.             width: 1200px;
  163.             height: 662px;
  164.             margin-bottom: 20px;
  165.             background: #DFDAD3;
  166.             position: relative;
  167.             .left {
  168.                 position: absolute;
  169.                 width: 660px;
  170.                 height: 100%;
  171.                 float: left;
  172.                 overflow: hidden;
  173.                 display: flex;
  174.                 align-items: center;
  175.                 justify-content: center;
  176.             }
  177.             .img {
  178.                 position: absolute;
  179.                 /* top: 5px; */
  180.                 /* left: 7px; */
  181.                 // max-width: 923px;
  182.                 // max-height: 460px;
  183.                 cursor: move;
  184.             }
  185.             .Button-area {
  186.                 width: 42px;
  187.                 height: 200px;
  188.                 // background-color: pink;
  189.                 position: absolute;
  190.                 right: -50px;
  191.                 top: 0px;
  192.                 ol {
  193.                     width: 100%;
  194.                     height: 100%;
  195.                     display: flex;
  196.                     flex-direction: column;
  197.                     justify-content: space-between;
  198.                     li {
  199.                         width: 43px;
  200.                         height: 42px;
  201.                         background: #A58773;
  202.                         cursor: pointer;
  203.                         // padding: 8px 8px;
  204.                         box-sizing: border-box;
  205.                         border-radius: 6px;
  206.                       display: flex;
  207.                       align-items: center;
  208.                       justify-content: center;
  209.                     }
  210.                     li:hover {
  211.                         background: #634d3f;
  212.                     }
  213.                 }
  214.             }
  215.         }
  216.     }
  217. }
  218. </style>
复制代码

  效果:
                         
  2:通过借鉴他人良好帖子所修改实现

  源码:
  1. <template>
  2.     <!-- 舆图库详情页 -->
  3.     <div class="mainPage">
  4.         <div class="watchMap">
  5.             <div class="imgBox" ref="maskBox" @mousedown="onmousedownHandle">
  6.                 <img :src="imageUrl" alt="" :style="{
  7.                     width: imgW + 'px',
  8.                     height: imgH + 'px',
  9.                     top: top + 'px',
  10.                     left: left + 'px',
  11.                     transform: scale,
  12.                 }" />
  13.             </div>
  14.             <div class="Tools">
  15.                 <div class="Tools-item" @click="imgScaleHandle(0.25)">
  16.                     大
  17.                 </div>
  18.                 <div class="Tools-item" @click="imgScaleHandle(-0.25)">
  19.                     小
  20.                 </div>
  21.                 <div class="Tools-item">
  22.                     藏
  23.                 </div>
  24.                 <div class="Tools-item" @click="
  25.     downloadByBlob(
  26.         'https://img2.baidu.com/it/u=1395980100,2999837177&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=675',
  27.         'name'
  28.     )
  29.                 ">
  30.                     下载
  31.                 </div>
  32.             </div>
  33.         </div>
  34.     </div>
  35. </template>
  36. <script>
  37. export default {
  38.     data() {
  39.         return {
  40.             imageUrl:
  41.                 "https://img2.baidu.com/it/u=1395980100,2999837177&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=675",
  42.             imgW: 0,
  43.             imgH: 0,
  44.             deg: 0,
  45.             top: 0,
  46.             left: 0,
  47.             scale: "scale(1)",
  48.             size: 0,
  49.             mousewheelevt: null,
  50.         };
  51.     },
  52.     mounted() {
  53.         //初始化图片
  54.         this.initImage();
  55.         // 兼容火狐浏览器
  56.         this.mousewheelevt = /Firefox/i.test(navigator.userAgent)
  57.             ? "DOMMouseScroll"
  58.             : "mousewheel";
  59.         // 为空间区域绑定鼠标滚轮事件 =》 处理函数是wheelHandle
  60.         // 如果你监听了window的scroll或者touchmove事件,你应该把passive设置为true,这样滚动就会流畅很多
  61.         this.$refs.maskBox.addEventListener(this.mousewheelevt, this.wheelHandle);
  62.     },
  63.     beforeDestroy() {
  64.         //取消监听
  65.         this.$refs.maskBox.removeEventListener(
  66.             this.mousewheelevt,
  67.             this.wheelHandle
  68.         );
  69.     },
  70.     created() {
  71.         this.handleReset();
  72.     },
  73.     methods: {
  74.         /**
  75.          *
  76.          * 下載圖片
  77.          * **/
  78.         downloadByBlob(url, name) {
  79.             let image = new Image();
  80.             image.setAttribute("crossOrigin", "anonymous");
  81.             image.src = url;
  82.             image.onload = () => {
  83.                 let canvas = document.createElement("canvas");
  84.                 canvas.width = image.width;
  85.                 canvas.height = image.height;
  86.                 let ctx = canvas.getContext("2d");
  87.                 ctx.drawImage(image, 0, 0, image.width, image.height);
  88.                 canvas.toBlob((blob) => {
  89.                     let url = URL.createObjectURL(blob);
  90.                     this.download(url, name);
  91.                     // 用完释放URL对象
  92.                     URL.revokeObjectURL(url);
  93.                 });
  94.             };
  95.         },
  96.         download(href, name) {
  97.             let eleLink = document.createElement("a");
  98.             eleLink.download = name;
  99.             eleLink.href = href;
  100.             eleLink.click();
  101.             eleLink.remove();
  102.         },
  103.         /**
  104.          * 重置
  105.          */
  106.         handleReset() {
  107.             this.imgW = 0;
  108.             this.imgH = 0;
  109.             this.top = 0;
  110.             this.left = 0;
  111.             this.deg = 0;
  112.             this.scale = "scale(1)";
  113.             this.size = 0;
  114.             this.initImage();
  115.         },
  116.         /**
  117.          * 获取图片的url
  118.          * @param {string} url
  119.          */
  120.         getImgSize(url) {
  121.             return new Promise((resolve, reject) => {
  122.                 let imgObj = new Image();
  123.                 imgObj.src = url;
  124.                 imgObj.onload = () => {
  125.                     resolve({
  126.                         width: imgObj.width,
  127.                         height: imgObj.height,
  128.                     });
  129.                 };
  130.             });
  131.         },
  132.         /**
  133.          * 初始化图片
  134.          */
  135.         async initImage() {
  136.             if (!this.imageUrl) {
  137.                 return;
  138.             }
  139.             let { width, height } = await this.getImgSize(this.imageUrl);
  140.             // 设置原始图片的大小
  141.             let realWidth = width;
  142.             let realHeight = height;
  143.             // 获取高宽比例
  144.             const whRatio = realWidth / realHeight;
  145.             const hwRatio = realHeight / realWidth;
  146.             //获取盒子的大小
  147.             const boxW = this.$refs.maskBox.clientWidth;
  148.             const boxH = this.$refs.maskBox.clientHeight;
  149.             if (realWidth >= realHeight) {
  150.                 this.imgH = hwRatio * boxW;
  151.                 const nih = this.imgH;
  152.                 if (nih > boxH) {
  153.                     this.imgH = boxH;
  154.                     this.imgW = whRatio * boxH;
  155.                 } else {
  156.                     this.imgW = boxW;
  157.                 }
  158.                 this.top = (boxH - this.imgH) / 2;
  159.                 this.left = (boxW - this.imgW) / 2;
  160.             } else {
  161.                 this.imgW = (boxH / realHeight) * realWidth;
  162.                 this.imgH = boxH;
  163.                 this.left = (boxW - this.imgW) / 2;
  164.             }
  165.         },
  166.         imgScaleHandle(zoom) {
  167.             this.size += zoom;
  168.             if (this.size < -0.5) {
  169.                 this.size = -0.5;
  170.             }
  171.             this.scale = `scale(${1 + this.size}) rotateZ(${this.deg}deg)`;
  172.         },
  173.         /**
  174.          * 鼠标滚动 实现放大缩小
  175.          */
  176.         wheelHandle(e) {
  177.             e.preventDefault();
  178.             const ev = e || window.event; // 兼容性处理 => 火狐浏览器判断滚轮的方向是属性 detail,谷歌和ie浏览器判断滚轮滚动的方向是属性 wheelDelta
  179.             // dir = -dir; // dir > 0 => 表示的滚轮是向上滚动,否则是向下滚动 => 范围 (-120 ~ 120)
  180.             const dir = ev.detail ? ev.detail * -120 : ev.wheelDelta;
  181.             //滚动的数值 / 2000 => 表示滚动的比例,用此比例作为图片缩放的比例
  182.             this.imgScaleHandle(dir / 2000);
  183.         },
  184.         /**
  185.          * 处理图片拖动
  186.          */
  187.         onmousedownHandle(e) {
  188.             const that = this;
  189.             this.$refs.maskBox.onmousemove = function (el) {
  190.                 const ev = el || window.event; // 阻止默认事件
  191.                 ev.preventDefault();
  192.                 that.left += ev.movementX;
  193.                 that.top += ev.movementY;
  194.             };
  195.             this.$refs.maskBox.onmouseup = function () {
  196.                 // 鼠标抬起时将操作区域的鼠标按下和抬起事件置为null 并初始化
  197.                 that.$refs.maskBox.onmousemove = null;
  198.                 that.$refs.maskBox.onmouseup = null;
  199.             };
  200.             if (e.preventDefault) {
  201.                 e.preventDefault();
  202.             } else {
  203.                 return false;
  204.             }
  205.         },
  206.     },
  207. };
  208. </script>
  209. <style lang="scss" scoped>
  210. .world_map {
  211.     width: 1200px;
  212.     margin: 41px auto;
  213.     .name {
  214.         width: 95px;
  215.         margin: 0 auto;
  216.         font-size: 22px;
  217.         font-family: "st";
  218.         font-weight: bold;
  219.         color: pink;
  220.         line-height: 30px;
  221.         letter-spacing: 1px;
  222.     }
  223. }
  224. .watchMap {
  225.     width: 1200px;
  226.     height: 662px;
  227.     background: pink;
  228.     position: relative;
  229.     // overflow: hidden;
  230.     margin-left: 360px;
  231.     .imgBox {
  232.         width: 100%;
  233.         height: 100%;
  234.         overflow: hidden;
  235.         position: relative;
  236.         img {
  237.             cursor: move;
  238.             position: absolute;
  239.         }
  240.     }
  241.     .Tools {
  242.         width: 43px;
  243.         min-height: 100px;
  244.         position: absolute;
  245.         right: -50px;
  246.         top: 0;
  247.         user-select: none;
  248.         .Tools-item {
  249.             width: 100%;
  250.             height: 44px;
  251.             background: pink;
  252.             margin-bottom: 5px;
  253.             display: flex;
  254.             justify-content: center;
  255.             align-items: center;
  256.             cursor: pointer;
  257.         }
  258.         .Tools-item:hover{
  259.             background-color: red;
  260.             color: #fff;
  261.         }
  262.     }
  263. }
  264. </style>
复制代码

  效果:@韩桑
              
来源:https://blog.csdn.net/qq_63310300/article/details/128872535
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则