canvas绘制矩形选框裁剪图片,图片可放大缩小拖拽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
:root {
--canvasWidth: 814px;
--canvasHeight: 800px;
}
canvas {
border: 1px solid black;
}
.canvas-box {
width: 814px;
height: 800px;
}
</style>
</head>
<body>
<div class="canvas-box" style="width: var(--canvasWidth); height: var(--canvasHeight);">
<canvas id="myCanvas" width="814" height="800"></canvas>
</div>
<div>
<button onclick="zoomIn()">放大</button>
<button onclick="zoomOut()">缩小</button>
<button onclick="drag()">拖拽</button>
<button onclick="select()">选取</button>
</div>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = "./img/asd.png";
var isDragging = false;
var startX, startY, endX, endY;
let scaleValue = 1
let scaleDiff = 0.1
let imgWidth, imgHeight;
let isInit = true
var containerWidth = canvas.width;
var containerHeight = canvas.height;
let imgObj = { x: 0, y: 0 }
let downDiffX, downDiffY
let isSelect = false
let drawRectArr = localStorage.getItem('drawRectArr') ? JSON.parse(localStorage.getItem('drawRectArr')) : []
img.onload = function () {
imgWidth = img.width;
imgHeight = img.height;
let isUpright = imgWidth < imgHeight ? true : false
if (isInit && containerHeight < imgHeight && isUpright) {
scaleValue = containerHeight / imgHeight
isInit = false
} else if (isInit && containerWidth < imgWidth && !isUpright) {
scaleValue = containerWidth / imgWidth
isInit = false
}
imgObj.x = (containerWidth - imgWidth * scaleValue) / 2
imgObj.y = (containerHeight - imgHeight * scaleValue) / 2
console.log(imgObj.x, imgObj.y)
drawImageScaled();
};
function drawImageScaled() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, imgObj.x, imgObj.y, imgWidth * scaleValue, imgHeight * scaleValue);
}
canvas.addEventListener('wheel', function (event) {
event.preventDefault();
var delta = Math.sign(event.deltaY);
if (delta > 0) {
zoomOut()
} else {
zoomIn()
}
}, { passive: false });
function drawRect(x1, y1, x2, y2, color = 'blue') {
ctx.strokeStyle = color;
ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
}
canvas.addEventListener('mousedown', function (e) {
isDragging = true;
startX = e.offsetX;
startY = e.offsetY;
downDiffX = e.x - imgObj.x
downDiffY = e.y - imgObj.y
});
canvas.addEventListener('mousemove', function (e) {
if (!isDragging) return;
if ( !isSelect) {
endX = e.offsetX;
endY = e.offsetY;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawImageScaled();
drawRect(startX, startY, endX, endY, 'red');
} else {
imgObj.x = e.x - downDiffX
imgObj.y = e.y - downDiffY
drawImageScaled()
}
});
canvas.addEventListener('mouseup', function () {
let interceptObj = {
cropStartX: preciseCalc(startX - imgObj.x, scaleValue, '/'),
cropStartY: preciseCalc(startY - imgObj.y, scaleValue, '/'),
cropEndX: preciseCalc(endX - imgObj.x, scaleValue, '/'),
cropEndY: preciseCalc(endY - imgObj.y, scaleValue, '/')
}
if (startX > endX) {
interceptObj.cropStartX = preciseCalc(endX - imgObj.x, scaleValue, '/'),
interceptObj.cropEndX = preciseCalc(startX - imgObj.x, scaleValue, '/')
}
if (startY > endY) {
interceptObj.cropStartY = preciseCalc(endY - imgObj.y, scaleValue, '/')
interceptObj.cropEndY = preciseCalc(startY - imgObj.y, scaleValue, '/')
}
drawRectArr.push(interceptObj)
localStorage.setItem('drawRectArr', JSON.stringify(drawRectArr))
isDragging = false;
if (!isSelect) {
cropImg(interceptObj)
}
});
function zoomIn() {
if (scaleValue < 3) {
scaleValue = preciseCalc(scaleValue, scaleDiff, '+')
img.style.transform = `scale(${scaleValue})`;
}
drawImageScaled();
}
function zoomOut() {
if (scaleValue > 0.1) {
console.log(scaleValue)
scaleValue = preciseCalc(scaleValue, scaleDiff, '-')
console.log(scaleValue)
img.style.transform = `scale(${scaleValue})`;
}
drawImageScaled();
}
function drag() {
isSelect = true
}
function select() {
isSelect = false
}
function preciseCalc(num1, num2, operator = '+') {
const precision = 10 ** 10;
switch (operator) {
case '+':
return parseFloat((Math.round(num1 * precision) + Math.round(num2 * precision)) / precision);
case '-':
return parseFloat((Math.round(num1 * precision) - Math.round(num2 * precision)) / precision);
case '/':
return parseFloat((num1 / num2).toFixed(2));
default:
throw new Error('Unsupported operation');
}
}
const cropImg = ({ cropStartX, cropStartY, cropEndX, cropEndY }) => {
const cropCanvas = document.createElement('canvas')
cropCanvas.width = cropEndX - cropStartX
cropCanvas.height = cropEndY - cropStartY
const ctx = cropCanvas.getContext('2d')
ctx.drawImage(img, cropStartX, cropStartY, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height)
img.crossOrigin = "anonymous";
console.log(cropCanvas.toDataURL())
document.body.appendChild(cropCanvas)
}
</script>
</body>
</html>