canvas 截图效果

1. 初始化 canvas

2. 绘制图片

3. 绘制蒙层

4.截图的矩形=> 蒙层上分鼠标移动范围内进行图片截图绘制

5. 在鼠标移动时改变矩形,而且修改 源(新的)图像绘制到目标(已有)的图像上(globalCompositeOperation)

6. 获取截图的数据 放入另一个 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>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="box">
<input type="file" accesskey="image/*" class="inp" />
<canvas class="canvas"></canvas>
</div>
<script src="./index.js"></script>
</body>
</html>
const inp = document.querySelector(".box .inp");
const cvs = document.querySelector(".box .canvas");
const ctx = cvs.getContext("2d");
const newCvs = document.createElement("canvas");
const newCtx = newCvs.getContext("2d");
const img = new Image();
//存放鼠标按下的坐标
let initPos = [];
//存放截图最终的坐标
let newCanvas = [];
//主函数
const init = () => {
bindEvent();
};
//绑定事件
const bindEvent = () => {
inp.addEventListener("change", handleFileSelect, false);
cvs.addEventListener("mousedown", handleCvsMousedown, false);
};
//初始化canvas并展示图片
const handleFileSelect = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = function (e) {
img.src = e.target.result;
img.onload = function () {
initCvs();
drawMask(0, 0, cvs.width, cvs.height, 0.5);
if (newCanvas.length) {
document.body.removeChild(newCvs);
}
};
};
reader.readAsDataURL(file);
};
//初始化canvas
const initCvs = () => {
cvs.width = 700;
cvs.height = 700;
cvs.style.display = "block";
ctx.drawImage(img, 0, 0, cvs.width, cvs.height);
};

//绘制蒙层
const drawMask = (x, y, wid, hei, opacity) => {
ctx.fillStyle = `rgba(0,0,0,${opacity})`;
ctx.fillRect(x, y, wid, hei);
};

//鼠标移动持续触发裁剪框大小
const handleCvsMousedown = (e) => {
initPos = [e.offsetX, e.offsetY];
cvs.addEventListener("mousemove", handleCvsMousemove, false);
cvs.addEventListener("mouseup", handleCvsMouseup, false);
cvs.addEventListener("mouseleave", handleCvsMouseup, false);
cvs.addEventListener("mouseenter", handleCvsMouseup, false);
};

//开始裁剪
const handleCvsMousemove = (e) => {
const { offsetX: endX, offsetY: endY } = e;
const [startX, startY] = initPos;
//得到裁剪框的宽高
const wid = endX - startX;
const hei = endY - startY;
//收集展示裁剪后的图片坐标
newCanvas = [startX, startY, wid, hei];
//清除画布
ctx.clearRect(0, 0, cvs.width, cvs.height);
drawMask(0, 0, cvs.width, cvs.height, 0.5);
//绘制裁剪框
drawSelect(cvs.width, cvs.height, wid, hei);
};
//绘制裁剪框
const drawSelect = (cvsWid, cvsHei, wid, hei) => {
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.fillRect(...initPos, wid, hei);
ctx.globalCompositeOperation = "destination-over";
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, cvsWid, cvsHei);
};

//完成截图选区,取消对应事件 生成一个新的canvas展示截取后的图片
const handleCvsMouseup = (e) => {
cvs.removeEventListener("mousemove", handleCvsMousemove, false);
cvs.removeEventListener("mouseup", handleCvsMouseup, false);
cvs.removeEventListener("mouseleave", handleCvsMouseup, false);
cvs.removeEventListener("mouseenter", handleCvsMouseup, false);
drawNewCvs(newCanvas);
};
//展示截取的图片
const drawNewCvs = (newCanvas) => {
const data = ctx.getImageData(...newCanvas);
newCtx.clearRect(...newCanvas);
newCvs.width = newCanvas[2];
newCvs.height = newCanvas[3];
newCtx.putImageData(data, 0, 0);
document.body.appendChild(newCvs);
};
init();