UNPKG

jjb-lc-designable

Version:

基于alibaba-designable源码二次封装的表单设计器。

470 lines (468 loc) 15.7 kB
import { isValidNumber } from './types'; export function isRect(rect) { return rect?.x && rect?.y && rect?.width && rect?.height; } export function isPoint(val) { return isValidNumber(val?.x) && isValidNumber(val?.y); } export function isLineSegment(val) { return isPoint(val?.start) && isPoint(val?.end); } export class Point { constructor(x, y) { this.x = x; this.y = y; } } export class Rect { x = 0; y = 0; width = 0; height = 0; constructor(x, y, width, height) { this.x = x; this.y = y; this.width = width; this.height = height; } get left() { return this.x; } get right() { return this.x + this.width; } get top() { return this.y; } get bottom() { return this.y + this.height; } } export class LineSegment { constructor(start, end) { this.start = { ...start }; this.end = { ...end }; } } export let RectQuadrant = /*#__PURE__*/function (RectQuadrant) { RectQuadrant["Inner1"] = "I1"; RectQuadrant["Inner2"] = "I2"; RectQuadrant["Inner3"] = "I3"; RectQuadrant["Inner4"] = "I4"; RectQuadrant["Outer1"] = "O1"; RectQuadrant["Outer2"] = "O2"; RectQuadrant["Outer3"] = "O3"; RectQuadrant["Outer4"] = "O4"; return RectQuadrant; }({}); //内部第八象限 export function isPointInRect(point, rect, sensitive = true) { const boundSensor = value => { if (!sensitive) return 0; const sensor = value * 0.1; if (sensor > 20) return 20; if (sensor < 10) return 10; return sensor; }; return point.x >= rect.x + boundSensor(rect.width) && point.x <= rect.x + rect.width - boundSensor(rect.width) && point.y >= rect.y + boundSensor(rect.height) && point.y <= rect.y + rect.height - boundSensor(rect.height); } export function isEqualRect(target, source) { return target?.x === source?.x && target.y === source.y && target.width === source.width && target.height === source.height; } export function getRectPoints(source) { const p1 = new Point(source.x, source.y); const p2 = new Point(source.x + source.width, source.y); const p3 = new Point(source.x + source.width, source.y + source.height); const p4 = new Point(source.x, source.y + source.height); return [p1, p2, p3, p4]; } export function isRectInRect(target, source) { const [p1, p2, p3, p4] = getRectPoints(target); return isPointInRect(p1, source, false) && isPointInRect(p2, source, false) && isPointInRect(p3, source, false) && isPointInRect(p4, source, false); } export function isCrossRectInRect(target, source) { const targetCenterPoint = new Point(target.x + target.width / 2, target.y + target.height / 2); const sourceCenterPoint = new Point(source.x + source.width / 2, source.y + source.height / 2); return Math.abs(targetCenterPoint.x - sourceCenterPoint.x) <= target.width / 2 + source.width / 2 && Math.abs(targetCenterPoint.y - sourceCenterPoint.y) <= target.height / 2 + source.height / 2; } /** * 计算点在矩形的哪个象限 * @param point * @param rect */ export function calcQuadrantOfPointToRect(point, rect) { const isInner = isPointInRect(point, rect); if (point.x <= rect.x + rect.width / 2) { if (point.y <= rect.y + rect.height / 2) { if (isInner) { return RectQuadrant.Inner1; } else { return RectQuadrant.Outer1; } } else { if (isInner) { return RectQuadrant.Inner4; } else { return RectQuadrant.Outer4; } } } else { if (point.y <= rect.y + rect.height / 2) { if (isInner) { return RectQuadrant.Inner2; } else { return RectQuadrant.Outer2; } } else { if (isInner) { return RectQuadrant.Inner3; } else { return RectQuadrant.Outer3; } } } } export function calcDistanceOfPointToRect(point, rect) { let minX = Math.min(Math.abs(point.x - rect.x), Math.abs(point.x - (rect.x + rect.width))); let minY = Math.min(Math.abs(point.y - rect.y), Math.abs(point.y - (rect.y + rect.height))); if (point.x >= rect.x && point.x <= rect.x + rect.width) { minX = 0; } if (point.y >= rect.y && point.y <= rect.y + rect.height) { minY = 0; } return Math.sqrt(minX ** 2 + minY ** 2); } export function calcDistancePointToEdge(point, rect) { const distanceTop = Math.abs(point.y - rect.y); const distanceBottom = Math.abs(point.y - (rect.y + rect.height)); const distanceLeft = Math.abs(point.x - rect.x); const distanceRight = Math.abs(point.x - (rect.x + rect.width)); return Math.min(distanceTop, distanceBottom, distanceLeft, distanceRight); } export function isNearAfter(point, rect, inline = false) { if (inline) { return Math.abs(point.x - rect.x) + Math.abs(point.y - rect.y) > Math.abs(point.x - (rect.x + rect.width)) + Math.abs(point.y - (rect.y + rect.height)); } return Math.abs(point.y - rect.y) > Math.abs(point.y - (rect.y + rect.height)); } /** * 计算点鱼矩形的相对位置信息 * @param point * @param rect */ export function calcRelativeOfPointToRect(point, rect) { const distance = calcDistanceOfPointToRect(point, rect); const quadrant = calcQuadrantOfPointToRect(point, rect); return { quadrant, distance }; } export function calcBoundingRect(rects) { if (!rects?.length) return; if (rects?.length === 1 && !rects[0]) return; let minTop = Infinity; let maxBottom = -Infinity; let minLeft = Infinity; let maxRight = -Infinity; rects.forEach(item => { const rect = new Rect(item.x, item.y, item.width, item.height); if (rect.top <= minTop) { minTop = rect.top; } if (rect.bottom >= maxBottom) { maxBottom = rect.bottom; } if (rect.left <= minLeft) { minLeft = rect.left; } if (rect.right >= maxRight) { maxRight = rect.right; } }); return new Rect(minLeft, minTop, maxRight - minLeft, maxBottom - minTop); } export function calcRectByStartEndPoint(startPoint, endPoint, scrollX = 0, scrollY = 0) { let drawStartX = 0, drawStartY = 0; if (endPoint.x + scrollX >= startPoint.x && endPoint.y + scrollY >= startPoint.y) { //4象限 drawStartX = startPoint.x; drawStartY = startPoint.y; return new Rect(drawStartX - scrollX, drawStartY - scrollY, Math.abs(endPoint.x - startPoint.x + scrollX), Math.abs(endPoint.y - startPoint.y + scrollY)); } else if (endPoint.x + scrollX < startPoint.x && endPoint.y + scrollY < startPoint.y) { //1象限 drawStartX = endPoint.x; drawStartY = endPoint.y; return new Rect(drawStartX, drawStartY, Math.abs(endPoint.x - startPoint.x + scrollX), Math.abs(endPoint.y - startPoint.y + scrollY)); } else if (endPoint.x + scrollX < startPoint.x && endPoint.y + scrollY >= startPoint.y) { //3象限 drawStartX = endPoint.x; drawStartY = startPoint.y; return new Rect(drawStartX - scrollX, drawStartY - scrollY, Math.abs(endPoint.x - startPoint.x + scrollX), Math.abs(endPoint.y - startPoint.y + scrollY)); } else { //2象限 drawStartX = startPoint.x; drawStartY = endPoint.y; return new Rect(drawStartX, drawStartY, Math.abs(endPoint.x - startPoint.x + scrollX), Math.abs(endPoint.y - startPoint.y + scrollY)); } } export function calcEdgeLinesOfRect(rect) { return { v: [new LineSegment(new Point(rect.x, rect.y), new Point(rect.x, rect.y + rect.height)), new LineSegment(new Point(rect.x + rect.width / 2, rect.y), new Point(rect.x + rect.width / 2, rect.y + rect.height)), new LineSegment(new Point(rect.x + rect.width, rect.y), new Point(rect.x + rect.width, rect.y + rect.height))], h: [new LineSegment(new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y)), new LineSegment(new Point(rect.x, rect.y + rect.height / 2), new Point(rect.x + rect.width, rect.y + rect.height / 2)), new LineSegment(new Point(rect.x, rect.y + rect.height), new Point(rect.x + rect.width, rect.y + rect.height))] }; } export function calcRectOfAxisLineSegment(line) { if (!isLineSegment(line)) return; const isXAxis = line.start.x === line.end.x; return new Rect(line.start.x, line.start.y, isXAxis ? 0 : line.end.x - line.start.x, isXAxis ? line.end.y - line.start.y : 0); } export function calcSpaceBlockOfRect(target, source, type) { const targetRect = new Rect(target.x, target.y, target.width, target.height); const sourceRect = new Rect(source.x, source.y, source.width, source.height); if (sourceRect.bottom < targetRect.top && sourceRect.left > targetRect.right) return; if (sourceRect.top > targetRect.bottom && sourceRect.left > targetRect.right) return; if (sourceRect.bottom < targetRect.top && sourceRect.right < targetRect.left) return; if (sourceRect.top > targetRect.bottom && sourceRect.right < targetRect.left) return; if (sourceRect.bottom < targetRect.top) { const distance = targetRect.top - sourceRect.bottom; const left = Math.min(sourceRect.left, targetRect.left); const right = Math.max(sourceRect.right, targetRect.right); if (type && type !== 'top') return; return { type: 'top', distance, rect: new Rect(left, sourceRect.bottom, right - left, distance) }; } else if (sourceRect.top > targetRect.bottom) { const distance = sourceRect.top - targetRect.bottom; const left = Math.min(sourceRect.left, targetRect.left); const right = Math.max(sourceRect.right, targetRect.right); if (type && type !== 'bottom') return; return { type: 'bottom', distance, rect: new Rect(left, targetRect.bottom, right - left, distance) }; } else if (sourceRect.right < targetRect.left) { const distance = targetRect.left - sourceRect.right; const top = Math.min(sourceRect.top, targetRect.top); const bottom = Math.max(sourceRect.bottom, targetRect.bottom); if (type && type !== 'left') return; return { type: 'left', distance, rect: new Rect(sourceRect.right, top, distance, bottom - top) }; } else if (sourceRect.left > targetRect.right) { const distance = sourceRect.left - targetRect.right; const top = Math.min(sourceRect.top, targetRect.top); const bottom = Math.max(sourceRect.bottom, targetRect.bottom); if (type && type !== 'right') return; return { type: 'right', distance, rect: new Rect(targetRect.right, top, distance, bottom - top) }; } } export function calcExtendsLineSegmentOfRect(targetRect, referRect) { if (referRect.right < targetRect.right && targetRect.left <= referRect.right) { //右侧 if (referRect.bottom < targetRect.top) { //上方 return { start: { x: referRect.right, y: referRect.bottom }, end: { x: targetRect.right, y: referRect.bottom } }; } else if (referRect.top > targetRect.bottom) { //下方 return { start: { x: referRect.right, y: referRect.top }, end: { x: targetRect.right, y: referRect.top } }; } } else if (referRect.left > targetRect.left && targetRect.right >= referRect.left) { //左侧 if (referRect.bottom < targetRect.top) { //上方 return { start: { x: targetRect.left, y: referRect.bottom }, end: { x: referRect.left, y: referRect.bottom } }; } else if (referRect.top > targetRect.bottom) { //下方 return { start: { x: targetRect.left, y: referRect.top }, end: { x: referRect.left, y: referRect.top } }; } } if (referRect.top < targetRect.top && targetRect.bottom >= referRect.top) { //refer在上方 if (referRect.right < targetRect.left) { //右侧 return { start: { x: referRect.right, y: referRect.bottom }, end: { x: referRect.right, y: targetRect.bottom } }; } else if (referRect.left > targetRect.right) { //左侧 return { start: { x: referRect.left, y: referRect.bottom }, end: { x: referRect.left, y: targetRect.bottom } }; } } else if (referRect.bottom > targetRect.bottom && referRect.top <= targetRect.bottom) { //refer下方 if (referRect.right < targetRect.left) { //右侧 return { start: { x: referRect.right, y: targetRect.top }, end: { x: referRect.right, y: referRect.top } }; } else if (referRect.left > targetRect.right) { //左侧 return { start: { x: referRect.left, y: targetRect.top }, end: { x: referRect.left, y: referRect.top } }; } } } export function calcOffsetOfSnapLineSegmentToEdge(line, current) { const edges = calcEdgeLinesOfRect(current); const isVerticalLine = line.start.x === line.end.x; if (isVerticalLine) { return { x: calcMinDistanceValue(edges.x, line.start.x) - current.x, y: 0 }; } function calcEdgeLinesOfRect(rect) { return { x: [rect.x, rect.x + rect.width / 2, rect.x + rect.width], y: [rect.y, rect.y + rect.height / 2, rect.y + rect.height] }; } function calcMinDistanceValue(edges, targetValue) { let minDistance = Infinity, minDistanceIndex = -1; for (let i = 0; i < edges.length; i++) { const distance = Math.abs(edges[i] - targetValue); if (minDistance > distance) { minDistance = distance; minDistanceIndex = i; } } return edges[minDistanceIndex]; } return { x: 0, y: calcMinDistanceValue(edges.y, line.start.y) - current.y }; } export function calcDistanceOfSnapLineToEdges(line, edges) { let distance = Infinity; if (line?.start?.y === line?.end?.y) { edges.h.forEach(target => { const _distance = Math.abs(target.start.y - line.start.y); if (_distance < distance) { distance = _distance; } }); } else if (line?.start?.x === line?.end?.x) { edges.v.forEach(target => { const _distance = Math.abs(target.start.x - line.start.x); if (_distance < distance) { distance = _distance; } }); } else { throw new Error('can not calculate slash distance'); } return distance; } export function calcCombineSnapLineSegment(target, source) { if (target.start.x === target.end.x) { return new LineSegment(new Point(target.start.x, target.start.y > source.start.y ? source.start.y : target.start.y), new Point(target.start.x, target.end.y > source.end.y ? target.end.y : source.end.y)); } return new LineSegment(new Point(target.start.x > source.start.x ? source.start.x : target.start.x, target.start.y), new Point(target.end.x > source.end.x ? target.end.x : source.end.x, target.end.y)); } export function calcClosestEdges(line, edges) { let result; let distance = Infinity; if (line?.start?.y === line?.end?.y) { edges.h.forEach(target => { const _distance = Math.abs(target.start.y - line.start.y); if (_distance < distance) { distance = _distance; result = target; } }); } else if (line?.start?.x === line?.end?.x) { edges.v.forEach(target => { const _distance = Math.abs(target.start.x - line.start.x); if (_distance < distance) { distance = _distance; result = target; } }); } else { throw new Error('can not calculate slash distance'); } return [distance, result]; }