fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
84 lines (77 loc) • 2.7 kB
text/typescript
import type { FabricObject, Point, TOriginX, TOriginY } from 'fabric';
import { aligningLineConfig } from '../constant';
import { getDistance } from './basic';
type CollectPointProps = {
activeObject: FabricObject;
point: Point;
list: Point[];
isScale: boolean;
index: number;
};
const originXArr: TOriginX[] = ['left', 'center', 'right'];
const originYArr: TOriginY[] = ['top', 'center', 'bottom'];
export function collectVerticalPoint(props: CollectPointProps) {
const aligningLineMargin = aligningLineConfig.margin;
const { activeObject, isScale, index, point, list } = props;
const { dis, arr } = getDistanceList(point, list, 'x');
const margin = aligningLineMargin / (activeObject.canvas?.getZoom() ?? 1);
if (dis > margin) return [];
let v = arr[arr.length - 1].x - point.x;
const dir = index == 0 || index == 3 ? -1 : 1;
v *= dir;
const { width, scaleX, left } = activeObject;
const dim = activeObject._getTransformedDimensions();
const sx = (v + dim.x) / dim.x;
if (isScale) activeObject.set('scaleX', scaleX * sx);
else activeObject.set('width', width * sx);
const dArr = [0, (v / 2) * dir, v * dir];
if (dir < 0) dArr.reverse();
const d = dArr[originXArr.indexOf(activeObject.originX)];
activeObject.set('left', left + d);
activeObject.setCoords();
return arr.map((item) => ({
x: item.x,
y1: item.y,
y2: point.y,
}));
}
export function collectHorizontalPoint(props: CollectPointProps) {
const aligningLineMargin = aligningLineConfig.margin;
const { activeObject, isScale, index, point, list } = props;
const { dis, arr } = getDistanceList(point, list, 'y');
const margin = aligningLineMargin / (activeObject.canvas?.getZoom() ?? 1);
if (dis > margin) return [];
let v = arr[arr.length - 1].y - point.y;
const dir = index < 2 ? -1 : 1;
v *= dir;
const { height, scaleY, top } = activeObject;
const dim = activeObject._getTransformedDimensions();
const sy = (v + dim.y) / dim.y;
if (isScale) activeObject.set('scaleY', scaleY * sy);
else activeObject.set('height', height * sy);
const dArr = [0, (v / 2) * dir, v * dir];
if (dir < 0) dArr.reverse();
const d = dArr[originYArr.indexOf(activeObject.originY)];
activeObject.set('top', top + d);
activeObject.setCoords();
return arr.map((item) => ({
y: item.y,
x1: item.x,
x2: point.x,
}));
}
function getDistanceList(point: Point, list: Point[], type: 'x' | 'y') {
let dis = Infinity;
let arr: Point[] = [];
for (const item of list) {
const v = getDistance(point[type], item[type]);
if (dis > v) {
arr = [];
dis = v;
}
if (dis == v) {
arr.push(item);
}
}
return { dis, arr };
}