vue 鼠标拖动选取框进行截图功能

先上效果图

在这里插入图片描述

截图原图注意路径位置, 以及大小 ,此demo的大小标签大小写死的,css 的宽高需要与图片一致

HTML代码

<template>
  <div class="box" id="box">
    <img src="../assets/demo.png" alt="" class="img-box" draggable="false">
    <!-- 截取坐标在图上的位置 -->
    <div class="box-max"
         @mousedown="handleMousedown"
         @mousemove="handleMousemove"
         @mouseup="handleMouseup"
    >
      <div class="active-box" @mousedown.stop="handleBoxMax"
           :style="{ width: activeWidth + 'px', height: activeHeight + 'px', left: activeLeft + 'px', top: activeTop + 'px' }"
      >
      </div>
    </div>
  </div>
  <div>
    <p style="display: none">画布首次裁剪</p>
    <canvas id="imgDom" style="display: none">画布首次裁剪</canvas>
    <p>画布最终规则裁剪</p>
    <canvas id="imgClipDom">画布最终规则裁剪</canvas>
  </div>
</template>

JS代码

<script setup>
import demoIMg from '../assets/demo.png'
import { ref } from "vue";
const activeLeft = ref(0)
const activeTop = ref(0)
const activeWidth = ref(0)
const activeHeight = ref(0)
let drawActiveBox = false
function handleMousedown(event) {
  console.log(event)
  drawActiveBox = !drawActiveBox
  if (!drawActiveBox) return interceptImg()
  activeWidth.value = 0
  activeHeight.value = 0
  activeLeft.value = event.offsetX
  activeTop.value = event.offsetY
}
function handleMousemove(event) { // 鼠标移动时画出轮廓
  const dom = document.getElementById('box')
  console.log(dom.offsetLeft)
  if (drawActiveBox) {
    activeWidth.value = event.clientX - activeLeft.value - dom.offsetLeft
    activeHeight.value = event.clientY - activeTop.value - dom.offsetTop
    console.log(event)
    // console.log(activeWidth.value, activeHeight.value)
  }
}
function handleMouseup() { // 松开时关闭移动绘制
  drawActiveBox = false
  console.log('松开鼠标')
  interceptImg()
}
function handleBoxMax () {
  console.log('移动框框')
}
function interceptImg() {
  // 截取指定坐标的图片信息
  var canvas = document.getElementById('imgDom');
  var ctx = canvas.getContext('2d');
  var img = new Image();
  img.src = demoIMg;
  // img.crossOrigin = ''
  var clipPos = [
    [activeLeft.value, activeTop.value],
    [activeLeft.value + activeWidth.value, activeTop.value],
    [activeLeft.value + activeWidth.value, activeTop.value + activeHeight.value],
    [activeLeft.value, activeTop.value + activeHeight.value]
  ] // 获取截取框的位置
  img.onload = function () {
    // console.log(this)
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.beginPath();
    ctx.moveTo(clipPos[0][0], clipPos[0][1]);
    ctx.lineTo(clipPos[1][0], clipPos[1][1]);
    ctx.lineTo(clipPos[2][0], clipPos[2][1]);
    ctx.lineTo(clipPos[3][0], clipPos[3][1]);
    // 裁剪后其他区域不可见,然后再绘制图片,就会只剩下指定的区域;
    // 实际上画布还是原本图片的宽高大小,只是指定的区域里面才有图片内容,其他区域是空白的;
    // 画布裁剪只能裁剪出规则的矩形,这时候需要算出指定有效坐标区域的最小外接矩形,使不规则转变为规则
    ctx.clip();
    ctx.drawImage(img, 0, 0, img.width, img.height);
    // 当绘制图形不规则时,根据左右上下的坐标得到不规则图形外的最小外接矩形,进行规则裁剪
    // 首先循环获取最小的x,y 和 最大的x,y
    var minLeft = clipPos[0][0], maxLeft = clipPos[0][0], minTop = clipPos[0][1], maxTop = clipPos[0][1]
    for (let index = 1; index < clipPos.length; index++) {
      const item = clipPos[index];
      if (item[0] < minLeft) {
        minLeft = item[0]
      }
      if (item[0] > maxLeft) {
        maxLeft = item[0]
      }
      if (item[1] < minTop) {
        minTop = item[1]
      }
      if (item[1] > maxTop) {
        maxTop = item[1]
      }
    }
    // 得到规则矩形对应区域的图片数据
    console.log(minLeft, minTop, maxLeft - minLeft, maxTop - minTop)
    var imgClipData = ctx.getImageData(minLeft, minTop, maxLeft - minLeft, maxTop - minTop);
    var canvas2 = document.getElementById("imgClipDom")
    var cxt2 = canvas2.getContext("2d")
    canvas2.width = imgClipData.width
    canvas2.height = imgClipData.height
    cxt2.putImageData(imgClipData, 0, 0, 0, 0, imgClipData.width, imgClipData.height)
    // 可以转换为base64进行查看
    var img2 = canvas2.toDataURL("image/png");
    // console.log(img2)
  }
}
</script>

CSS代码

<style scoped>
.box {
  width: 1125px;
  height: 543px;
  position: relative;
}
.box-max{
  position: absolute;
  width: 1125px;
  height: 543px;
  z-index: 9;
}
.img-box {
  z-index: 1;
  position: absolute;
}

canvas {
  border: 1px solid #666;
}

.active-box {
  position: absolute;
  width: 0;
  height: 0;
  border: 2px solid red;
  top: 0;
  left: 0;
  z-index: 9;
}
</style>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现modal鼠标拖动功能,可以使用Vue3的自定义指令和事件监听。 首先,在modal的HTML元素上使用自定义指令,例如 `v-draggable`。然后,在自定义指令中注册鼠标事件,当鼠标按下时,记录当前鼠标位置和modal位置的差值。当鼠标移动时,根据差值更新modal的位置。 下面是一个简单的示例代码: ```html <template> <div class="modal" v-draggable> <div class="modal-header">Modal Header</div> <div class="modal-body">Modal Body</div> </div> </template> <script> import { directive } from 'vue' const draggableDirective = directive((el) => { let isDragging = false let startX = 0 let startY = 0 let initialX = 0 let initialY = 0 const handleMouseDown = (event) => { isDragging = true startX = event.clientX startY = event.clientY initialX = el.offsetLeft initialY = el.offsetTop document.addEventListener('mousemove', handleMouseMove) document.addEventListener('mouseup', handleMouseUp) } const handleMouseMove = (event) => { if (isDragging) { const dx = event.clientX - startX const dy = event.clientY - startY el.style.left = `${initialX + dx}px` el.style.top = `${initialY + dy}px` } } const handleMouseUp = () => { isDragging = false document.removeEventListener('mousemove', handleMouseMove) document.removeEventListener('mouseup', handleMouseUp) } el.addEventListener('mousedown', handleMouseDown) return () => { el.removeEventListener('mousedown', handleMouseDown) document.removeEventListener('mousemove', handleMouseMove) document.removeEventListener('mouseup', handleMouseUp) } }) export default { directives: { draggable: draggableDirective } } </script> ``` 在这个示例中,我们定义了一个名为 `draggable` 的自定义指令,并在modal的HTML元素上应用了这个指令。在自定义指令中,我们监听了 `mousedown`、`mousemove` 和 `mouseup` 事件,并通过计算鼠标移动的距离来更新modal的位置。最后,我们将自定义指令注册到了Vue组件中,以便在模板中使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值