fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 13.8 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":[],"sources":["../../extensions/aligning_guidelines/index.ts"],"sourcesContent":["import {\n type BasicTransformEvent,\n type Canvas,\n type FabricObject,\n type Point,\n util,\n} from 'fabric';\nimport {\n collectHorizontalPoint,\n collectVerticalPoint,\n} from './util/collect-point';\nimport {\n drawHorizontalLine,\n drawLine,\n drawPointList,\n drawVerticalLine,\n drawX,\n} from './util/draw';\nimport { collectLine } from './util/collect-line';\nimport type { AligningLineConfig, OriginMap } from './typedefs';\nimport { getObjectsByTarget } from './util/get-objects-by-target';\nimport { getContraryMap, getPointMap } from './util/basic';\n\ntype TransformEvent = BasicTransformEvent & {\n target: FabricObject;\n};\n\nexport class AligningGuidelines {\n canvas: Canvas;\n horizontalLines = new Set<string>();\n verticalLines = new Set<string>();\n cacheMap = new Map<string, Point[]>();\n /**\n * When we drag to resize using center points like mt, ml, mb, and mr,\n * we do not need to draw line segments; we only need to draw the target points.\n */\n onlyDrawPoint = false;\n /** Alignment method is required when customizing. */\n contraryOriginMap: OriginMap = {\n tl: ['right', 'bottom'],\n tr: ['left', 'bottom'],\n br: ['left', 'top'],\n bl: ['right', 'top'],\n mt: ['center', 'bottom'],\n mr: ['left', 'center'],\n mb: ['center', 'top'],\n ml: ['right', 'center'],\n };\n xSize = 2.4;\n lineDash: number[] | undefined;\n /** At what distance from the shape does alignment begin? */\n margin = 4;\n /** Aligning line dimensions */\n width = 1;\n /** Aligning line color */\n color = 'rgba(255,0,0,0.9)';\n /** Close Vertical line, default false. */\n closeVLine = false;\n /** Close horizontal line, default false. */\n closeHLine = false;\n\n constructor(canvas: Canvas, options: Partial<AligningLineConfig> = {}) {\n this.canvas = canvas;\n Object.assign(this, options);\n\n this.mouseUp = this.mouseUp.bind(this);\n this.scalingOrResizing = this.scalingOrResizing.bind(this);\n this.moving = this.moving.bind(this);\n this.beforeRender = this.beforeRender.bind(this);\n this.afterRender = this.afterRender.bind(this);\n\n this.initBehavior();\n }\n initBehavior() {\n this.canvas.on('mouse:up', this.mouseUp);\n this.canvas.on('object:resizing', this.scalingOrResizing);\n this.canvas.on('object:scaling', this.scalingOrResizing);\n this.canvas.on('object:moving', this.moving);\n this.canvas.on('before:render', this.beforeRender);\n this.canvas.on('after:render', this.afterRender);\n }\n /** Returns shapes that can draw aligning lines, default returns all shapes on the canvas excluding groups. */\n getObjectsByTarget(target: FabricObject) {\n return getObjectsByTarget(target);\n }\n /** When the user customizes the controller, this property is set to enable or disable automatic alignment through point scaling/resizing. */\n getPointMap(target: FabricObject) {\n return getPointMap(target);\n }\n /** When the user customizes the controller, this property is used to enable or disable alignment positioning through points. */\n getContraryMap(target: FabricObject) {\n return getContraryMap(target);\n }\n /** Users can customize. */\n getCaCheMapValue(object: FabricObject) {\n const cacheKey = [\n object.calcTransformMatrix().toString(),\n object.width,\n object.height,\n ].join();\n const cacheValue = this.cacheMap.get(cacheKey);\n if (cacheValue) return cacheValue;\n const value = object.getCoords();\n value.push(object.getCenterPoint());\n this.cacheMap.set(cacheKey, value);\n return value;\n }\n drawLine(origin: Point, target: Point) {\n drawLine.call(this, origin, target);\n }\n drawX(point: Point, dir: number) {\n drawX.call(this, point, dir);\n }\n mouseUp() {\n this.verticalLines.clear();\n this.horizontalLines.clear();\n this.cacheMap.clear();\n this.canvas.requestRenderAll();\n }\n\n scalingOrResizing(e: TransformEvent) {\n const target = e.target;\n // We need to obtain the real-time coordinates of the current object, so we need to update them in real-time\n target.setCoords();\n // The value of action can be scaleX, scaleY, scale, resize, etc.\n // If it does not start with \"scale,\" it is considered a modification of size.\n const isScale = String(e.transform.action).startsWith('scale');\n this.verticalLines.clear();\n this.horizontalLines.clear();\n\n const objects = this.getObjectsByTarget(target);\n // When the shape is flipped, the tl obtained through getCoords is actually tr,\n // and tl is actually tr. We need to make correction adjustments.\n // tr <-> tl、 bl <-> br、 mb <-> mt、 ml <-> mr\n let corner = e.transform.corner;\n if (target.flipX) {\n if (corner.includes('l')) corner = corner.replace('l', 'r');\n else if (corner.includes('r')) corner = corner.replace('r', 'l');\n }\n if (target.flipY) {\n if (corner.includes('t')) corner = corner.replace('t', 'b');\n else if (corner.includes('b')) corner = corner.replace('b', 't');\n }\n\n // Obtain the coordinates of the current operation point through the value of corner.\n // users can be allowed to customize and pass in custom corners.\n const pointMap = this.getPointMap(target);\n if (!(corner in pointMap)) return;\n this.onlyDrawPoint = corner.includes('m');\n if (this.onlyDrawPoint) {\n const angle = target.getTotalAngle();\n // When the shape is rotated, it is meaningless to draw points using the center point.\n if (angle % 90 != 0) return;\n }\n // If manipulating tl, then when the shape changes size, it should be positioned by br,\n // and the same applies to others.\n // users can be allowed to customize and pass in custom corners.\n const contraryMap = this.getContraryMap(target);\n const point = pointMap[corner];\n let diagonalPoint = contraryMap[corner];\n // When holding the centerKey (default is altKey), the shape will scale based on the center point, with the reference point being the center.\n const isCenter =\n e.transform.original.originX == 'center' &&\n e.transform.original.originY == 'center';\n if (isCenter) {\n const p = target.group\n ? point.transform(\n util.invertTransform(target.group.calcTransformMatrix()),\n )\n : point;\n diagonalPoint = diagonalPoint.add(p).scalarDivide(2);\n }\n const uniformIsToggled = e.e[this.canvas.uniScaleKey!];\n let isUniform =\n (this.canvas.uniformScaling && !uniformIsToggled) ||\n (!this.canvas.uniformScaling && uniformIsToggled);\n // When controlling through the center point,\n // if isUniform is true, it actually changes the skew, so it is meaningless.\n if (this.onlyDrawPoint) isUniform = false;\n\n const list: Point[] = [];\n for (const object of objects) {\n const d = this.getCaCheMapValue(object);\n list.push(...d);\n }\n\n const props = {\n target,\n point,\n diagonalPoint,\n corner,\n list,\n isScale,\n isUniform,\n isCenter,\n };\n\n // Obtain horizontal and vertical reference lines.\n const noNeedToCollectV =\n this.onlyDrawPoint && (corner.includes('t') || corner.includes('b'));\n const noNeedToCollectH =\n this.onlyDrawPoint && (corner.includes('l') || corner.includes('r'));\n const vList = noNeedToCollectV\n ? []\n : collectVerticalPoint.call(this, props);\n const hList = noNeedToCollectH\n ? []\n : collectHorizontalPoint.call(this, props);\n vList.forEach((o) => {\n // Objects cannot be deduplicated; convert them to strings for deduplication.\n this.verticalLines.add(JSON.stringify(o));\n });\n hList.forEach((o) => {\n // Objects cannot be deduplicated; convert them to strings for deduplication.\n this.horizontalLines.add(JSON.stringify(o));\n });\n }\n moving(e: TransformEvent) {\n const target = e.target;\n // We need to obtain the real-time coordinates of the current object, so we need to update them in real-time\n target.setCoords();\n this.onlyDrawPoint = false;\n this.verticalLines.clear();\n this.horizontalLines.clear();\n\n // Find the shapes associated with the current graphic to draw reference lines for it.\n const objects = this.getObjectsByTarget(target);\n const points: Point[] = [];\n // Collect all the points to draw reference lines.\n for (const object of objects) points.push(...this.getCaCheMapValue(object));\n\n // Obtain horizontal and vertical reference lines.\n const { vLines, hLines } = collectLine.call(this, target, points);\n vLines.forEach((o) => {\n // Objects cannot be deduplicated; convert them to strings for deduplication.\n this.verticalLines.add(JSON.stringify(o));\n });\n hLines.forEach((o) => {\n // Objects cannot be deduplicated; convert them to strings for deduplication.\n this.horizontalLines.add(JSON.stringify(o));\n });\n }\n beforeRender() {\n this.canvas.clearContext(this.canvas.contextTop);\n }\n afterRender() {\n if (this.onlyDrawPoint) {\n drawPointList.call(this);\n } else {\n drawVerticalLine.call(this);\n drawHorizontalLine.call(this);\n }\n }\n\n dispose() {\n this.canvas.off('mouse:up', this.mouseUp);\n this.canvas.off('object:resizing', this.scalingOrResizing);\n this.canvas.off('object:scaling', this.scalingOrResizing);\n this.canvas.off('object:moving', this.moving);\n this.canvas.off('before:render', this.beforeRender);\n this.canvas.off('after:render', this.afterRender);\n }\n}\n"],"mappings":"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"}