先上效果图
截图原图注意路径位置, 以及大小 ,此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>