@zhuxiaozy/clipimg
Version:
362 lines • 13.8 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import Mouse from "./mouse.js";
``;
let mouse;
export default class ClipImg {
constructor(config) {
this.reviewSrc = '';
this.controllerIsDown = false;
this.el = config.el;
this.reviewCall = config.reviewCall;
this.canvas = document.createElement("canvas");
this.controllerBox = document.createElement("div");
this.context = this.canvas.getContext("2d");
this.imgCtx = {
x: 0,
y: 0,
width: 0,
height: 0,
n: 0,
img: document.createElement("img"),
draw: () => {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.context.drawImage(this.imgCtx.img, this.imgCtx.x, this.imgCtx.y, this.imgCtx.width, this.imgCtx.height);
this.getClipView();
},
};
mouse = new Mouse();
this.init();
}
init() {
this.el.style.position = "relative";
this.el.appendChild(this.canvas);
this.canvas.width = this.el.clientWidth;
this.canvas.height = this.el.clientHeight;
this.getEvent();
this.createControlBox();
this.createControlBoxImg();
}
createControlBoxImg() {
if (this.reviewSrc) {
this.controllerBox.style.backgroundImage = `url('${this.reviewSrc}')`;
this.controllerBox.style.backgroundSize = '100% 100%';
this.controllerBox.style.backgroundPosition = '0 0';
}
}
getEvent() {
let isDown = false;
let lx;
let ly;
this.el.addEventListener("mousedown", (e) => {
if (this.controllerIsDown) {
return;
}
const offsetX = e.pageX - this.el.getBoundingClientRect().x;
const offsetY = e.pageY - this.el.getBoundingClientRect().y;
lx = this.imgCtx.x - offsetX;
ly = this.imgCtx.y - offsetY;
isDown = true;
});
this.el.addEventListener("mousemove", (e) => {
if (this.controllerIsDown) {
return;
}
const offsetX = e.pageX - this.el.getBoundingClientRect().x;
const offsetY = e.pageY - this.el.getBoundingClientRect().y;
if (offsetX > this.imgCtx.x &&
offsetX < this.imgCtx.x + this.imgCtx.width &&
offsetY > this.imgCtx.y &&
offsetY < this.imgCtx.y + this.imgCtx.height) {
if (isDown) {
this.imgCtx.x = offsetX + lx;
this.imgCtx.y = offsetY + ly;
this.imgCtx.draw();
}
}
});
this.el.addEventListener("mouseleave", () => {
isDown = false;
});
this.el.addEventListener("mouseup", () => {
isDown = false;
});
const n = 8;
mouse.scrollDown = () => {
this.imgCtx.width += n;
if (this.imgCtx.width <= this.canvas.width * 3) {
this.imgCtx.height = this.imgCtx.width / this.imgCtx.n;
this.imgCtx.x -= n / 2;
this.imgCtx.y -= n / 2;
}
else {
this.imgCtx.width = this.canvas.width * 3;
this.imgCtx.height = this.imgCtx.width / this.imgCtx.n;
}
this.imgCtx.draw();
};
mouse.scrollUp = () => {
this.imgCtx.width -= n;
if (this.imgCtx.width >= 50) {
this.imgCtx.height = this.imgCtx.width / this.imgCtx.n;
this.imgCtx.x += n / 2;
this.imgCtx.y += n / 2;
}
else {
this.imgCtx.width = 50;
this.imgCtx.height = this.imgCtx.width / this.imgCtx.n;
}
this.imgCtx.draw();
};
}
setImg(file) {
const img = new Image();
img.src = URL.createObjectURL(file);
img.onload = () => {
const imgWidth = img.width;
const imgHeight = img.height;
const n = imgWidth / imgHeight;
let width = this.canvas.width;
let height = this.canvas.height;
if (n > 1.7777777) {
width = this.canvas.width;
height = width / n;
}
else if (n < 1.7777777) {
height = this.canvas.height;
width = height * n;
}
const x = (this.canvas.width - width) / 2;
const y = (this.canvas.height - height) / 2;
this.imgCtx.x = x;
this.imgCtx.y = y;
this.imgCtx.width = width;
this.imgCtx.height = height;
this.imgCtx.n = n;
this.imgCtx.img = img;
this.imgCtx.draw();
};
}
setSize(width = 160, height = 90) {
this.controllerBox.style.width = width + "px";
this.controllerBox.style.height = height + "px";
}
createControlBox() {
this.controllerBox.style.cssText = `
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
border: 1px solid #5c5c5c;
`;
this.setSize(160, 90);
const pointBtn = [
this.createControlBtn(8, 8, "lt"),
this.createControlBtn(8, 8, "rt"),
this.createControlBtn(8, 8, "lb"),
this.createControlBtn(8, 8, "rb"),
];
pointBtn.forEach((btn) => {
this.controllerBox.appendChild(btn);
});
this.el.appendChild(this.controllerBox);
}
createControlBtn(width, height, type) {
const div = document.createElement("div");
div.style.cssText = `
width: ${width}px;
height: ${height}px;
position: absolute;
cursor: pointer;
background: #cccccc;
`;
div.setAttribute("type", type);
if (type === "lt" || type === "rt") {
div.style.top = -height / 2 + "px";
}
if (type === "lt" || type === "lb") {
div.style.left = -width / 2 + "px";
}
if (type === "lb" || type === "rb") {
div.style.bottom = -height / 2 + "px";
}
if (type === "rt" || type === "rb") {
div.style.right = -width / 2 + "px";
}
let divType = "";
let n = 0;
div.addEventListener("mousedown", () => {
n = this.controllerBox.offsetWidth / this.controllerBox.offsetHeight;
divType = div.getAttribute("type");
this.controllerIsDown = true;
});
this.el.addEventListener("mouseup", () => {
divType = "";
this.controllerIsDown = false;
});
this.el.addEventListener("mouseleave", () => {
divType = "";
this.controllerIsDown = false;
});
this.el.addEventListener("mousemove", (e) => {
if (this.controllerIsDown) {
const parent = div.parentNode;
const x = e.pageX - this.el.getBoundingClientRect().x;
if (divType === "lt" || divType === "lb") {
let width = this.canvas.width - x * 2;
width = width > this.canvas.width ? this.canvas.width : width;
width = width < 100 ? 100 : width;
if (width / n > this.canvas.height) {
parent.style.width = this.canvas.height * n + "px";
parent.style.height = this.canvas.height + "px";
return;
}
parent.style.width = width + "px";
parent.style.height = width / n + "px";
this.getClipView();
}
if (divType === "rt" || divType === "rb") {
let width = this.canvas.width - (this.canvas.width - x) * 2;
width = width > this.canvas.width ? this.canvas.width : width;
width = width < 100 ? 100 : width;
if (width / n > this.canvas.height) {
parent.style.width = this.canvas.height * n + "px";
parent.style.height = this.canvas.height + "px";
return;
}
parent.style.width = width + "px";
parent.style.height = width / n + "px";
this.getClipView();
}
}
}, true);
return div;
}
computeSize(width) {
}
getClipView() {
if (!this.context) {
return;
}
const opt = this.controllerBox.getBoundingClientRect();
const x = this.controllerBox.offsetLeft - opt.width / 2;
const y = this.controllerBox.offsetTop - opt.height / 2;
const width = opt.width;
const height = opt.height;
const data = this.context.getImageData(x, y, width, height);
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.putImageData(data, 0, 0);
this.reviewSrc = canvas.toDataURL('image/jpeg');
this.createControlBoxImg();
if (this.reviewCall) {
this.reviewCall(this.reviewSrc);
}
}
getClipData(size = 4096) {
return new Promise((resolve) => {
document.body.appendChild(this.imgCtx.img);
const opt = this.controllerBox.getBoundingClientRect();
const x = this.controllerBox.offsetLeft - opt.width / 2;
const y = this.controllerBox.offsetTop - opt.height / 2;
const width = opt.width;
const height = opt.height;
const n = this.imgCtx.img.offsetWidth / this.imgCtx.width;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = this.imgCtx.img.offsetWidth;
canvas.height = this.imgCtx.img.offsetHeight;
document.body.removeChild(this.imgCtx.img);
ctx.drawImage(this.imgCtx.img, 0, 0, canvas.width, canvas.height);
const data = ctx.getImageData((x - this.imgCtx.x) * n, (y - this.imgCtx.y) * n, width * n, height * n);
const canvas2 = document.createElement("canvas");
const ctx2 = canvas2.getContext("2d");
canvas2.width = width * n;
canvas2.height = height * n;
ctx2.putImageData(data, 0, 0);
canvas2.toBlob((blob) => __awaiter(this, void 0, void 0, function* () {
let blobs = yield this.compress(blob);
while (blobs.size / 1024 > size) {
blobs = yield this.compress(blobs);
}
const url = URL.createObjectURL(blobs);
resolve({
url: url,
blob: blobs,
});
}));
});
}
compress(blob) {
return new Promise((resolve) => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const img = new Image();
img.style.cssText = `
position:absolute;
top:-9999999px;
left:-99999999;
`;
document.body.appendChild(img);
img.onload = () => {
canvas.width = img.width * 0.9;
canvas.height = img.height * 0.9;
document.body.removeChild(img);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blobs) => {
resolve(blobs);
}, "image/jpeg");
};
img.src = URL.createObjectURL(blob);
});
}
clientX(el) {
return this.pageX(el) - this.scrollX();
}
clientY(el) {
return this.pageY(el) - this.scrollY();
}
pageX(el) {
let parent = el;
let x = 0;
while (parent) {
x += parent.offsetLeft;
parent = parent.offsetParent;
}
return x;
}
pageY(el) {
let parent = el;
let y = 0;
while (parent) {
y += parent.offsetTop;
parent = parent.offsetParent;
}
return y;
}
scrollX(elOrWindow) {
let x = 0;
if (elOrWindow) {
x = elOrWindow.scrollLeft;
}
return x;
}
scrollY(elOrWindow) {
let y = 0;
if (elOrWindow) {
y = elOrWindow.scrollTop;
}
return y;
}
}
window['ClipImg'] = ClipImg;
//# sourceMappingURL=imgClip.js.map