fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
224 lines (223 loc) • 7.34 kB
JavaScript
import { getContraryMap, getPointMap } from "./util/basic.mjs";
import { collectHorizontalPoint, collectVerticalPoint } from "./util/collect-point.mjs";
import { drawHorizontalLine, drawLine, drawPointList, drawVerticalLine, drawX } from "./util/draw.mjs";
import { collectLine } from "./util/collect-line.mjs";
import { getObjectsByTarget } from "./util/get-objects-by-target.mjs";
import { _defineProperty } from "../_virtual/_@oxc-project_runtime@0.122.0/helpers/defineProperty.mjs";
import { util } from "fabric";
//#region extensions/aligning_guidelines/index.ts
var AligningGuidelines = class {
constructor(canvas, options = {}) {
_defineProperty(this, "canvas", void 0);
_defineProperty(this, "horizontalLines", /* @__PURE__ */ new Set());
_defineProperty(this, "verticalLines", /* @__PURE__ */ new Set());
_defineProperty(this, "cacheMap", /* @__PURE__ */ new Map());
_defineProperty(
this,
/**
* When we drag to resize using center points like mt, ml, mb, and mr,
* we do not need to draw line segments; we only need to draw the target points.
*/
"onlyDrawPoint",
false
);
_defineProperty(
this,
/** Alignment method is required when customizing. */
"contraryOriginMap",
{
tl: ["right", "bottom"],
tr: ["left", "bottom"],
br: ["left", "top"],
bl: ["right", "top"],
mt: ["center", "bottom"],
mr: ["left", "center"],
mb: ["center", "top"],
ml: ["right", "center"]
}
);
_defineProperty(this, "xSize", 2.4);
_defineProperty(this, "lineDash", void 0);
_defineProperty(
this,
/** At what distance from the shape does alignment begin? */
"margin",
4
);
_defineProperty(
this,
/** Aligning line dimensions */
"width",
1
);
_defineProperty(
this,
/** Aligning line color */
"color",
"rgba(255,0,0,0.9)"
);
_defineProperty(
this,
/** Close Vertical line, default false. */
"closeVLine",
false
);
_defineProperty(
this,
/** Close horizontal line, default false. */
"closeHLine",
false
);
this.canvas = canvas;
Object.assign(this, options);
this.mouseUp = this.mouseUp.bind(this);
this.scalingOrResizing = this.scalingOrResizing.bind(this);
this.moving = this.moving.bind(this);
this.beforeRender = this.beforeRender.bind(this);
this.afterRender = this.afterRender.bind(this);
this.initBehavior();
}
initBehavior() {
this.canvas.on("mouse:up", this.mouseUp);
this.canvas.on("object:resizing", this.scalingOrResizing);
this.canvas.on("object:scaling", this.scalingOrResizing);
this.canvas.on("object:moving", this.moving);
this.canvas.on("before:render", this.beforeRender);
this.canvas.on("after:render", this.afterRender);
}
/** Returns shapes that can draw aligning lines, default returns all shapes on the canvas excluding groups. */
getObjectsByTarget(target) {
return getObjectsByTarget(target);
}
/** When the user customizes the controller, this property is set to enable or disable automatic alignment through point scaling/resizing. */
getPointMap(target) {
return getPointMap(target);
}
/** When the user customizes the controller, this property is used to enable or disable alignment positioning through points. */
getContraryMap(target) {
return getContraryMap(target);
}
/** Users can customize. */
getCaCheMapValue(object) {
const cacheKey = [
object.calcTransformMatrix().toString(),
object.width,
object.height
].join();
const cacheValue = this.cacheMap.get(cacheKey);
if (cacheValue) return cacheValue;
const value = object.getCoords();
value.push(object.getCenterPoint());
this.cacheMap.set(cacheKey, value);
return value;
}
drawLine(origin, target) {
drawLine.call(this, origin, target);
}
drawX(point, dir) {
drawX.call(this, point, dir);
}
mouseUp() {
this.verticalLines.clear();
this.horizontalLines.clear();
this.cacheMap.clear();
this.canvas.requestRenderAll();
}
scalingOrResizing(e) {
const target = e.target;
target.setCoords();
const isScale = String(e.transform.action).startsWith("scale");
this.verticalLines.clear();
this.horizontalLines.clear();
const objects = this.getObjectsByTarget(target);
let corner = e.transform.corner;
if (target.flipX) {
if (corner.includes("l")) corner = corner.replace("l", "r");
else if (corner.includes("r")) corner = corner.replace("r", "l");
}
if (target.flipY) {
if (corner.includes("t")) corner = corner.replace("t", "b");
else if (corner.includes("b")) corner = corner.replace("b", "t");
}
const pointMap = this.getPointMap(target);
if (!(corner in pointMap)) return;
this.onlyDrawPoint = corner.includes("m");
if (this.onlyDrawPoint) {
if (target.getTotalAngle() % 90 != 0) return;
}
const contraryMap = this.getContraryMap(target);
const point = pointMap[corner];
let diagonalPoint = contraryMap[corner];
const isCenter = e.transform.original.originX == "center" && e.transform.original.originY == "center";
if (isCenter) {
const p = target.group ? point.transform(util.invertTransform(target.group.calcTransformMatrix())) : point;
diagonalPoint = diagonalPoint.add(p).scalarDivide(2);
}
const uniformIsToggled = e.e[this.canvas.uniScaleKey];
let isUniform = this.canvas.uniformScaling && !uniformIsToggled || !this.canvas.uniformScaling && uniformIsToggled;
if (this.onlyDrawPoint) isUniform = false;
const list = [];
for (const object of objects) {
const d = this.getCaCheMapValue(object);
list.push(...d);
}
const props = {
target,
point,
diagonalPoint,
corner,
list,
isScale,
isUniform,
isCenter
};
const noNeedToCollectV = this.onlyDrawPoint && (corner.includes("t") || corner.includes("b"));
const noNeedToCollectH = this.onlyDrawPoint && (corner.includes("l") || corner.includes("r"));
const vList = noNeedToCollectV ? [] : collectVerticalPoint.call(this, props);
const hList = noNeedToCollectH ? [] : collectHorizontalPoint.call(this, props);
vList.forEach((o) => {
this.verticalLines.add(JSON.stringify(o));
});
hList.forEach((o) => {
this.horizontalLines.add(JSON.stringify(o));
});
}
moving(e) {
const target = e.target;
target.setCoords();
this.onlyDrawPoint = false;
this.verticalLines.clear();
this.horizontalLines.clear();
const objects = this.getObjectsByTarget(target);
const points = [];
for (const object of objects) points.push(...this.getCaCheMapValue(object));
const { vLines, hLines } = collectLine.call(this, target, points);
vLines.forEach((o) => {
this.verticalLines.add(JSON.stringify(o));
});
hLines.forEach((o) => {
this.horizontalLines.add(JSON.stringify(o));
});
}
beforeRender() {
this.canvas.clearContext(this.canvas.contextTop);
}
afterRender() {
if (this.onlyDrawPoint) drawPointList.call(this);
else {
drawVerticalLine.call(this);
drawHorizontalLine.call(this);
}
}
dispose() {
this.canvas.off("mouse:up", this.mouseUp);
this.canvas.off("object:resizing", this.scalingOrResizing);
this.canvas.off("object:scaling", this.scalingOrResizing);
this.canvas.off("object:moving", this.moving);
this.canvas.off("before:render", this.beforeRender);
this.canvas.off("after:render", this.afterRender);
}
};
//#endregion
export { AligningGuidelines };
//# sourceMappingURL=index.mjs.map