@uploadcare/blocks
Version:
Building blocks for Uploadcare products integration
211 lines (187 loc) • 5.45 kB
JavaScript
import { THUMB_CORNER_SIZE, THUMB_OFFSET, THUMB_SIDE_SIZE } from './cropper-constants.js';
/**
* @param {SVGElement} node
* @param {{ [key: String]: String | Number }} attrs
*/
export function setSvgNodeAttrs(node, attrs) {
for (let p in attrs) node.setAttributeNS(null, p, attrs[p].toString());
}
/**
* @param {String} name
* @param {{ [key: String]: String | Number }} attrs
* @returns {SVGElement}
*/
export function createSvgNode(name, attrs = {}) {
let node = document.createElementNS('http://www.w3.org/2000/svg', name);
setSvgNodeAttrs(node, attrs);
return node;
}
/**
* @param {import('./types.js').Rectangle} rect
* @param {String} direction
*/
export function cornerPath(rect, direction) {
let { x, y, width, height } = rect;
let wMul = direction.includes('w') ? 0 : 1;
let hMul = direction.includes('n') ? 0 : 1;
let xSide = [-1, 1][wMul];
let ySide = [-1, 1][hMul];
let p1 = [
x + wMul * width + THUMB_OFFSET * xSide,
y + hMul * height + THUMB_OFFSET * ySide - THUMB_CORNER_SIZE * ySide,
];
let p2 = [x + wMul * width + THUMB_OFFSET * xSide, y + hMul * height + THUMB_OFFSET * ySide];
let p3 = [
x + wMul * width - THUMB_CORNER_SIZE * xSide + THUMB_OFFSET * xSide,
y + hMul * height + THUMB_OFFSET * ySide,
];
let path = `M ${p1[0]} ${p1[1]} L ${p2[0]} ${p2[1]} L ${p3[0]} ${p3[1]}`;
let center = p2;
return {
d: path,
center,
};
}
/**
* @param {import('./types.js').Rectangle} rect
* @param {String} direction
*/
export function sidePath(rect, direction) {
let { x, y, width, height } = rect;
let wMul = ['n', 's'].includes(direction) ? 0.5 : { w: 0, e: 1 }[direction];
let hMul = ['w', 'e'].includes(direction) ? 0.5 : { n: 0, s: 1 }[direction];
let xSide = [-1, 1][wMul];
let ySide = [-1, 1][hMul];
let p1, p2;
if (['n', 's'].includes(direction)) {
p1 = [x + wMul * width - THUMB_SIDE_SIZE / 2, y + hMul * height + THUMB_OFFSET * ySide];
p2 = [x + wMul * width + THUMB_SIDE_SIZE / 2, y + hMul * height + THUMB_OFFSET * ySide];
} else {
p1 = [x + wMul * width + THUMB_OFFSET * xSide, y + hMul * height - THUMB_SIDE_SIZE / 2];
p2 = [x + wMul * width + THUMB_OFFSET * xSide, y + hMul * height + THUMB_SIDE_SIZE / 2];
}
let path = `M ${p1[0]} ${p1[1]} L ${p2[0]} ${p2[1]}`;
let center = [p2[0] - (p2[0] - p1[0]) / 2, p2[1] - (p2[1] - p1[1]) / 2];
return { d: path, center };
}
/** @param {String} direction */
export function thumbCursor(direction) {
if (direction === '') {
return 'move';
}
if (['e', 'w'].includes(direction)) {
return 'ew-resize';
}
if (['n', 's'].includes(direction)) {
return 'ns-resize';
}
if (['nw', 'se'].includes(direction)) {
return 'nwse-resize';
}
return 'nesw-resize';
}
/**
* @param {import('./types.js').Rectangle} rect
* @param {[Number, Number]} delta
*/
export function moveRect(rect, [dx, dy]) {
return {
...rect,
x: rect.x + dx,
y: rect.y + dy,
};
}
/**
* @param {import('./types.js').Rectangle} rect1
* @param {import('./types.js').Rectangle} rect2
*/
export function constraintRect(rect1, rect2) {
let { x } = rect1;
let { y } = rect1;
if (rect1.x < rect2.x) {
x = rect2.x;
} else if (rect1.x + rect1.width > rect2.x + rect2.width) {
x = rect2.x + rect2.width - rect1.width;
}
if (rect1.y < rect2.y) {
y = rect2.y;
} else if (rect1.y + rect1.height > rect2.y + rect2.height) {
y = rect2.y + rect2.height - rect1.height;
}
return {
...rect1,
x,
y,
};
}
/**
* @param {import('./types.js').Rectangle} rect
* @param {[Number, Number]} delta
* @param {String} direction
*/
export function expandRect(rect, [dx, dy], direction) {
let { x, y, width, height } = rect;
if (direction.includes('n')) {
y += dy;
height -= dy;
}
if (direction.includes('s')) {
height += dy;
}
if (direction.includes('w')) {
x += dx;
width -= dx;
}
if (direction.includes('e')) {
width += dx;
}
return {
x,
y,
width,
height,
};
}
/**
* @param {import('./types.js').Rectangle} rect1
* @param {import('./types.js').Rectangle} rect2
*/
export function intersectionRect(rect1, rect2) {
let leftX = Math.max(rect1.x, rect2.x);
let rightX = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
let topY = Math.max(rect1.y, rect2.y);
let bottomY = Math.min(rect1.y + rect1.height, rect2.y + rect2.height);
return { x: leftX, y: topY, width: rightX - leftX, height: bottomY - topY };
}
/**
* @param {import('./types.js').Rectangle} rect
* @param {[Number, Number]} minSize
* @param {String} direction
*/
export function minRectSize(rect, [minWidth, minHeight], direction) {
let { x, y, width, height } = rect;
if (direction.includes('n')) {
let prevHeight = height;
height = Math.max(minHeight, height);
y = y + prevHeight - height;
}
if (direction.includes('s')) {
height = Math.max(minHeight, height);
}
if (direction.includes('w')) {
let prevWidth = width;
width = Math.max(minWidth, width);
x = x + prevWidth - width;
}
if (direction.includes('e')) {
width = Math.max(minWidth, width);
}
return { x, y, width, height };
}
/**
* @param {import('./types.js').Rectangle} rect
* @param {[Number, Number]} point
*/
export function rectContainsPoint(rect, [x, y]) {
return rect.x <= x && x <= rect.x + rect.width && rect.y <= y && y <= rect.y + rect.height;
}