boris-react-image-crop
Version:
react image crop
226 lines (225 loc) • 11.1 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import styles from './imageCrop.module.scss';
import classnames from 'classnames/bind';
import { useRef } from 'react';
import { ORIGIN_POINT, LINE_DIR, POINT_DIR, clamp } from './data';
var cx = classnames.bind(styles);
function diffPoints(p1, p2) {
return { x: p1.x - p2.x, y: p1.y - p2.y };
}
function addPoints(p1, p2, minX, minY, maxX, maxY) {
if (minX === void 0) { minX = 0; }
if (minY === void 0) { minY = 0; }
if (maxX === void 0) { maxX = 0; }
if (maxY === void 0) { maxY = 0; }
var x = p1.x + p2.x;
var y = p1.y + p2.y;
return { x: clamp(x, minX, maxX), y: clamp(y, minY, maxY) };
}
var CropBox = function (_a) {
var imgRef = _a.imgRef, imgSrc = _a.imgSrc, imgSize = _a.imgSize, offset = _a.offset, setOffset = _a.setOffset, cropBoxSize = _a.cropBoxSize, setCropBoxSize = _a.setCropBoxSize;
var lastMousePosRef = useRef(ORIGIN_POINT);
var getEdgeWidth = function () { return imgSize.w - cropBoxSize.w; };
var getEdgeHeight = function () { return imgSize.h - cropBoxSize.h; };
// 이미지의 좌상단 꼭지점
var getOffsetTop = function () {
var el = imgRef.current;
var offset = (el === null || el === void 0 ? void 0 : el.getBoundingClientRect().top) || 0;
return offset;
};
var getOffsetLeft = function () {
var el = imgRef.current;
var offset = (el === null || el === void 0 ? void 0 : el.getBoundingClientRect().left) || 0;
return offset;
};
var startPan = function (e) {
e.preventDefault();
document.addEventListener('mousemove', moveCropBox);
document.addEventListener('mouseup', stopPan);
// e.clientX, Y = 뷰포트 내에서의 클릭 지점
lastMousePosRef.current = { x: e.clientX, y: e.clientY };
};
var moveCropBox = function (e) {
var lastMousePos = lastMousePosRef.current;
var currentMousePos = { x: e.clientX, y: e.clientY };
var mouseDiff = diffPoints(currentMousePos, lastMousePos);
lastMousePosRef.current = currentMousePos;
setOffset(function (prevOffset) { return addPoints(prevOffset, mouseDiff, 0, 0, getEdgeWidth(), getEdgeHeight()); });
};
var stopPan = function () {
document.removeEventListener('mousemove', moveCropBox);
document.removeEventListener('mouseup', stopPan);
};
var startSetCropBox = function (e, dir) {
e.preventDefault();
var eLineX = offset.x + cropBoxSize.w;
var wLineX = offset.x;
var sLineY = offset.y + cropBoxSize.h;
var nLineY = offset.y;
var setCropBox = function (e) {
var startPoint = { x: e.clientX, y: e.clientY };
setBox({
x: clamp(startPoint.x - getOffsetLeft(), 0, imgSize.w),
y: clamp(startPoint.y - getOffsetTop(), 0, imgSize.h)
});
};
var setBox = function (currentMousePos) {
var isCrossEL = !(wLineX + cropBoxSize.w > currentMousePos.x);
var isCrossWL = eLineX - cropBoxSize.w > currentMousePos.x;
var isCrossSL = !(nLineY + cropBoxSize.h > currentMousePos.y);
var isCrossNL = sLineY - cropBoxSize.h > currentMousePos.y;
var eXOffset = eLineX - cropBoxSize.w - (offset.x - currentMousePos.x);
var wXOffset = wLineX - (offset.x - currentMousePos.x);
var sYOffset = sLineY - cropBoxSize.h - (offset.y - currentMousePos.y);
var nYOffset = nLineY - (offset.y - currentMousePos.y);
var eCrossW = eLineX - cropBoxSize.w - currentMousePos.x;
var wCrossW = currentMousePos.x - wLineX - cropBoxSize.w;
var sCrossH = sLineY - cropBoxSize.h - currentMousePos.y;
var nCrossH = currentMousePos.y - nLineY - cropBoxSize.h;
var eW = cropBoxSize.w + currentMousePos.x - eLineX;
var wW = cropBoxSize.w + wLineX - currentMousePos.x;
var sH = cropBoxSize.h + currentMousePos.y - sLineY;
var nH = cropBoxSize.h + nLineY - currentMousePos.y;
switch (dir) {
case 'e':
if (isCrossWL) {
setOffset({ x: eXOffset, y: offset.y });
setCropBoxSize({ w: eCrossW, h: cropBoxSize.h });
}
else {
setCropBoxSize({ w: eW, h: cropBoxSize.h });
}
break;
case 'w':
if (isCrossEL) {
setCropBoxSize({ w: wCrossW, h: cropBoxSize.h });
}
else {
setOffset({ x: wXOffset, y: offset.y });
setCropBoxSize({ w: wW, h: cropBoxSize.h });
}
break;
case 's':
if (isCrossNL) {
setOffset({ x: offset.x, y: sYOffset });
setCropBoxSize({ w: cropBoxSize.w, h: sCrossH });
}
else {
setCropBoxSize({ w: cropBoxSize.w, h: sH });
}
break;
case 'n':
if (isCrossSL) {
setCropBoxSize({ w: cropBoxSize.w, h: nCrossH });
}
else {
setOffset({ x: offset.x, y: nYOffset });
setCropBoxSize({ w: cropBoxSize.w, h: nH });
}
break;
case 'se':
if (isCrossNL && isCrossWL) {
setOffset({ x: eXOffset, y: sYOffset });
setCropBoxSize({ w: eCrossW, h: sCrossH });
}
else if (isCrossWL) {
setOffset({ x: eXOffset, y: offset.y });
setCropBoxSize({ w: eCrossW, h: sH });
}
else if (isCrossNL) {
setOffset({ x: offset.x, y: sYOffset });
setCropBoxSize({ w: eW, h: sCrossH });
}
else {
setCropBoxSize({ w: eW, h: sH });
}
break;
case 'sw':
if (isCrossNL && isCrossEL) {
setOffset({ x: offset.x + cropBoxSize.w, y: nYOffset });
setCropBoxSize({ w: wCrossW, h: sCrossH });
}
else if (isCrossEL) {
setCropBoxSize({ w: wCrossW, h: sH });
}
else if (isCrossNL) {
setOffset({ x: wXOffset, y: nYOffset });
setCropBoxSize({ w: wW, h: sCrossH });
}
else {
setOffset({ x: wXOffset, y: offset.y });
setCropBoxSize({ w: wW, h: sH });
}
break;
case 'ne':
if (isCrossSL && isCrossWL) {
setOffset({ x: eXOffset, y: offset.y + cropBoxSize.h });
setCropBoxSize({ w: eCrossW, h: nCrossH });
}
else if (isCrossWL) {
setOffset({ x: eXOffset, y: nYOffset });
setCropBoxSize({ w: eCrossW, h: nH });
}
else if (isCrossSL) {
setCropBoxSize({ w: eW, h: nCrossH });
}
else {
setOffset({ x: offset.x, y: nYOffset });
setCropBoxSize({ w: eW, h: nH });
}
break;
case 'nw':
if (isCrossSL && isCrossEL) {
setCropBoxSize({ w: wCrossW, h: nCrossH });
}
else if (isCrossEL) {
setOffset({ x: offset.x + cropBoxSize.w, y: nYOffset });
setCropBoxSize({ w: wCrossW, h: nH });
}
else if (isCrossSL) {
setOffset({ x: wXOffset, y: offset.y + cropBoxSize.h });
setCropBoxSize({ w: wW, h: nCrossH });
}
else {
setOffset({ x: wXOffset, y: nYOffset });
setCropBoxSize({ w: wW, h: nH });
}
break;
}
};
var stopSetCropBox = function () {
document.removeEventListener('mousemove', setCropBox);
document.removeEventListener('mouseup', stopSetCropBox);
};
document.addEventListener('mousemove', setCropBox);
document.addEventListener('mouseup', stopSetCropBox);
};
var getDash = function () { return ['w', 'h'].map(function (dir) { return _jsx("span", { className: cx('dash', dir) }, dir); }); };
var getLine = function () {
return LINE_DIR.map(function (dir) { return (_jsx("span", { className: cx('line', dir), onMouseDown: function (e) { return startSetCropBox(e, dir); } }, dir)); });
};
var getPoints = function () {
return POINT_DIR.map(function (dir) { return (_jsx("span", { className: cx('point', dir), onMouseDown: function (e) { return startSetCropBox(e, dir); } }, dir)); });
};
return (_jsxs("div", __assign({ className: cx('cropBox'), style: {
width: "".concat(cropBoxSize.w, "px"),
height: "".concat(cropBoxSize.h, "px"),
transform: "translateX(".concat(offset.x, "px) translateY(").concat(offset.y, "px)"),
} }, { children: [_jsx("span", __assign({ className: cx('viewBox') }, { children: _jsx("img", { className: cx('viewImg'), src: imgSrc, alt: 'img', style: {
width: "".concat(imgSize.w, "px"),
height: "".concat(imgSize.h, "px"),
transform: "translateX(-".concat(offset.x, "px) translateY(-").concat(offset.y, "px)"),
} }) })), getDash(), _jsx("span", { className: cx('cross') }), _jsx("span", { className: cx('moveBox'), onMouseDown: startPan }), getLine(), getPoints()] })));
};
export default CropBox;