UNPKG

cut-image-upload

Version:

裁剪图片,自定义裁剪比例,矩形,圆形,不支持椭圆形

293 lines (270 loc) 10.6 kB
const initArea = (domId, cutWidth, cutHeight, cutType) => { let dom = document.getElementById(domId); let text = dom.innerText || "选择裁剪图片"; // <div style="width:100%;height:100%;background:rgba(96,96,96,.5);position:absolute;top:0;left:0;z-index:9;"> // </div> let areaHtml = `<header id="${domId}Header" class="img-header" style="position:relative;display:none;margin-bottom:20px;"> <canvas id="${domId}Canvas" ></canvas> </header>`; areaHtml += `<content id="${domId}Content" class="img-content" > <label class="img-content-button" style="margin-right:16px;position:relative;padding:9px 15px;background:#409eff;color:#fff;cursor:pointer;border-radius:3px;font-size:12px;font-weight:500;"> ${text} <input type="file" id="${domId}ContentFile" accept="image/*" style="width:100%;position:absolute;top:0;left:0;z-index:1;cursor:pointer;opacity:0;" /> </label> <label id="${domId}Enlarge" class="img-content-button" style="margin-right:16px;padding:9px 15px;background:#67c23a;color:#fff;cursor:pointer;border-radius:3px;font-size:12px;font-weight:500;">+放大</label> <label id="${domId}Narrow" class="img-content-button" style="margin-right:16px;padding:9px 15px;background:#67c23a;color:#fff;cursor:pointer;border-radius:3px;font-size:12px;font-weight:500;">-缩小</label> <label id="${domId}LeftRotation" class="img-content-button" style="margin-right:16px;padding:9px 15px;background:#67c23a;color:#fff;cursor:pointer;border-radius:3px;font-size:12px;font-weight:500;">左旋转</label> <label id="${domId}RightRotation" class="img-content-button" style="margin-right:16px;padding:9px 15px;background:#67c23a;color:#fff;cursor:pointer;border-radius:3px;font-size:12px;font-weight:500;">右旋转</label> </content>`; areaHtml += `<footer></footer>`; dom.innerHTML = areaHtml; let canvas = document.getElementById(`${domId}Canvas`); let context = canvas.getContext("2d"); let uploadImg, newWidth, newHeight, dataBase64, initWidth, initHeight; let clipX, clipY; //裁剪框的左上角坐标 let drawImage = () => { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(uploadImg, 0, 0, newWidth, newHeight); context.globalCompositeOperation = "source-over"; context.fillStyle = "RGBA(96,96,96,.5)"; //context.fillRect(0, 0, canvas.width, canvas.height); //矩形,上右下左 context.fillRect(0, 0, canvas.width, clipY); context.fillRect( cutWidth + clipX, clipY, canvas.width - (cutWidth + clipX), cutHeight ); context.fillRect( 0, cutHeight + clipY, canvas.width, canvas.height - (cutHeight + clipY) ); context.fillRect(0, clipY, clipX, cutHeight); //context.save(); if (cutType === "ellipse" && 1 === 2) { //椭圆不支持 //let kappa = 0.5522848; let kappaL = 1.2, kappaS = 0.8; //两直线加弧线 //左上 context.beginPath(); context.moveTo(clipX, clipY + cutHeight / 2); context.lineTo(clipX, clipY); context.lineTo(clipX + cutWidth / 2, clipY); context.bezierCurveTo( (clipX + cutWidth / 3) * kappaS, (clipY + cutHeight / 6) * kappaS, (clipX + cutWidth / 6) * kappaS, (clipY + cutHeight / 3) * kappaS, clipX, clipY + cutHeight / 2 ); context.stroke(); //右上 context.beginPath(); context.moveTo(clipX + cutWidth, clipY + cutHeight / 2); context.lineTo(clipX + cutWidth, clipY); context.lineTo(clipX + cutWidth / 2, clipY); context.bezierCurveTo( (clipX + (cutWidth * 2) / 3) * kappaL, (clipY + cutHeight / 6) * kappaS, (clipX + (cutWidth * 5) / 6) * kappaL, (clipY + cutHeight / 3) * kappaS, clipX + cutWidth, clipY + cutHeight / 2 ); context.stroke(); } else if (cutType === "circle") { //两直线加弧线 context.beginPath(); context.moveTo(clipX, clipY); context.lineTo(clipX + cutWidth, clipY); context.lineTo(clipX + cutWidth, clipY + cutHeight); context.lineTo(clipX, clipY + cutHeight); context.lineTo(clipX, clipY); context.arc( clipX + cutWidth / 2, clipY + cutHeight / 2, cutWidth / 2, 0, Math.PI * 2 ); context.fill("evenodd"); } window["cutCoordinate" + domId] = { clipX: clipX, clipY: clipY, cutWidth: cutWidth, cutHeight: cutHeight, cutType: cutType, }; }; /*坐标转换*/ // let windowToCanvas = function (x, y) { // let box = canvas.getBoundingClientRect(); //这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离 // return { // x: x - box.left - (box.width - canvas.width) / 2, // y: y - box.top - (box.height - canvas.height) / 2, // }; // }; let moveCutting = () => { //let box = canvas.getBoundingClientRect(); canvas.onmousedown = function (event) { canvas.onmousemove = function (evt) { //移动 canvas.style.cursor = "move"; clipX = clipX + evt.movementX; if (clipX < 0) { clipX = 0; } else if (clipX > canvas.width - cutWidth) { clipX = canvas.width - cutWidth; } clipY = clipY + evt.movementY; if (clipY < 0) { clipY = 0; } else if (clipY > canvas.height - cutHeight) { clipY = canvas.height - cutHeight; } drawImage(); //重新绘制图片 }; canvas.onmouseup = function () { canvas.onmousemove = null; canvas.onmouseup = null; canvas.style.cursor = "default"; }; }; canvas.onmousewheel = function (event) { let oldWidth = newWidth; if (event.wheelDeltaY > 0) { //向上滚动 newWidth += 10; newHeight = (newHeight / oldWidth) * newWidth; drawImage(); } else if (event.wheelDeltaY < 0) { //向下滚动 newWidth -= 10; if (newWidth < cutWidth) { newWidth = cutWidth; } newHeight = (newHeight / oldWidth) * newWidth; drawImage(); } }; }; document.getElementById(`${domId}ContentFile`).onchange = (e) => { let file = e.target.files[0]; let reader = new FileReader(); reader.onload = function (e) { //文件读取完成 if (typeof e.target.result === "object") { dataBase64 = window.URL.createObjectURL(new Blob([e.target.result])); } else { dataBase64 = e.target.result; } uploadImg = new Image(); uploadImg.src = dataBase64; uploadImg.onload = function () { let w = this.width, h = this.height; newWidth = cutWidth * 1.2; newHeight = (newWidth * h) / w; initWidth = newWidth; initHeight = newHeight; if (newHeight < cutHeight * 1.2) { newHeight = cutHeight * 1.2; newWidth = (newHeight * w) / h; } canvas.width = newWidth; canvas.height = newHeight; document.getElementById(`${domId}Header`).style.display = ""; document.getElementById(`${domId}Header`).style.width = newWidth + "px"; document.getElementById(`${domId}Header`).style.height = newHeight + "px"; clipX = (canvas.width - cutWidth) / 2; clipY = (canvas.height - cutHeight) / 2; drawImage(); moveCutting(); }; }; //正式读取文件 reader.readAsDataURL(file); }; //放大 document.getElementById(`${domId}Enlarge`).onclick = (e) => { if (!document.getElementById(`${domId}ContentFile`).value) { return; } let oldWidth = newWidth; newWidth += 10; newHeight = (newHeight / oldWidth) * newWidth; drawImage(); }; //缩小 document.getElementById(`${domId}Narrow`).onclick = (e) => { if (!document.getElementById(`${domId}ContentFile`).value) { return; } console.log("e", e); let oldWidth = newWidth; newWidth -= 10; if (newWidth < cutWidth) { newWidth = cutWidth; } newHeight = (newHeight / oldWidth) * newWidth; // let canvas4 = document.createElement("canvas"); // canvas4.width = initWidth; //newWidth; // canvas4.height = initHeight; //newHeight; // let context4 = canvas4.getContext("2d"); // context4.drawImage(uploadImg, 0, 0, newWidth, newHeight); // uploadImg.src = canvas4.toDataURL(); //context.setTransform(0.9, 0, 0, 0.9, 0, 0); drawImage(); }; //左旋转 document.getElementById(`${domId}LeftRotation`).onclick = (e) => { if (!document.getElementById(`${domId}ContentFile`).value) { return; } let canvas4 = document.createElement("canvas"); canvas4.width = newWidth; canvas4.height = newHeight; let context4 = canvas4.getContext("2d"); // 先位移坐标到中心 context4.translate(newWidth / 2, newHeight / 2); // 旋转90度 context4.rotate(-(90 * Math.PI) / 180); // 把定位中心移动到左上角 context4.translate((-1 * newWidth) / 2, (-1 * newHeight) / 2); // 坐标系还原到初始 //context4.setTransform(1, 0, 0, 1, 0, 0); context4.drawImage(uploadImg, 0, 0, newWidth, newHeight); uploadImg.src = canvas4.toDataURL(); drawImage(); }; //右旋转 document.getElementById(`${domId}RightRotation`).onclick = (e) => { if (!document.getElementById(`${domId}ContentFile`).value) { return; } let canvas4 = document.createElement("canvas"); canvas4.width = newWidth; canvas4.height = newHeight; let context4 = canvas4.getContext("2d"); // 先位移坐标到中心 context4.translate(newWidth / 2, newHeight / 2); // 旋转90度 context4.rotate((90 * Math.PI) / 180); // 把定位中心移动到左上角 context4.translate((-1 * newWidth) / 2, (-1 * newHeight) / 2); // 坐标系还原到初始 //context4.setTransform(1, 0, 0, 1, 0, 0); context4.drawImage(uploadImg, 0, 0, newWidth, newHeight); uploadImg.src = canvas4.toDataURL(); drawImage(); }; }; export default initArea;