{"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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"}