cut-image-upload
Version:
裁剪图片,自定义裁剪比例,矩形,圆形,不支持椭圆形
293 lines (270 loc) • 10.6 kB
JavaScript
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;