diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 0d05a959..08f147a2 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -1,6 +1,6 @@ import { fabric } from 'fabric' import { v4 as uuidv4 } from 'uuid' -import { getDirection } from '@/util/canvas-util' +import { getDirection, getDirectionByPoint } from '@/util/canvas-util' export const QLine = fabric.util.createClass(fabric.Line, { type: 'QLine', @@ -28,7 +28,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { this.setLength() - this.direction = options.direction ?? getDirection({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) + this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) this.startPoint = { x: this.x1, y: this.y1 } this.endPoint = { x: this.x2, y: this.y2 } @@ -91,13 +91,35 @@ export const QLine = fabric.util.createClass(fabric.Line, { this.text = thisText return } + let left, top + if (this.direction === 'left' || this.direction === 'right') { + left = (x1 + x2) / 2 + top = (y1 + y2) / 2 + 10 + } else if (this.direction === 'top' || this.direction === 'bottom') { + left = (x1 + x2) / 2 + 10 + top = (y1 + y2) / 2 + } + + const minX = this.left + const maxX = this.left + this.width + const minY = this.top + const maxY = this.top + this.length const text = new fabric.Textbox(this.length.toFixed(0).toString(), { - left: (x1 + x2) / 2, - top: (y1 + y2) / 2, + left: left, + top: top, fontSize: this.fontSize, - selectable: false, + minX, + maxX, + minY, + maxY, + parentDirection: this.direction, parentId: this.id, + editable: false, + selectable: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, name: 'lengthText', }) diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 1cd24f15..2990feb7 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -129,6 +129,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }) this.texts = null }) + + // polygon.fillCell({ width: 50, height: 30, padding: 10 }) }, initLines() { @@ -156,25 +158,19 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }, addLengthText() { + if (this.texts.length > 0) { + this.texts.forEach((text) => { + this.canvas.remove(text) + }) + } let points = this.getCurrentPoints() points.forEach((start, i) => { - const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id && obj.idx === i) - const end = points[(i + 1) % points.length] const dx = end.x - start.x const dy = end.y - start.y const length = Math.sqrt(dx * dx + dy * dy) - if (thisText) { - thisText.set({ - left: (start.x + points[(i + 1) % points.length].x) / 2, - top: (start.y + points[(i + 1) % points.length].y) / 2, - text: length.toFixed(0), - }) - return - } - const midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) // Create new text object if it doesn't exist @@ -182,8 +178,18 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { left: midPoint.x, top: midPoint.y, fontSize: this.fontSize, - selectable: false, parentId: this.id, + minX: Math.min(start.x, end.x), + maxX: Math.max(start.x, end.x), + minY: Math.min(start.y, end.y), + maxY: Math.max(start.y, end.y), + parentDirection: getDirectionByPoint(start, end), + dirty: true, + editable: false, + selectable: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, idx: i, name: 'lengthText', }) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 2740f669..9e359fb2 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -1,13 +1,6 @@ import { useEffect, useRef, useState } from 'react' import { fabric } from 'fabric' -import { - actionHandler, - anchorWrapper, - calculateIntersection, - distanceBetweenPoints, - polygonPositionHandler, - test, -} from '@/util/canvas-util' +import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util' import { useRecoilState } from 'recoil' import { canvasSizeState, fontSizeState } from '@/store/canvasAtom' @@ -104,6 +97,14 @@ export function useCanvas(id) { const addEventOnObject = (e) => { const target = e.target + + if (target.type === 'QPolygon' || target.type === 'QLine') { + const textObjs = canvas?.getObjects().filter((obj) => obj.name === 'lengthText') + textObjs.forEach((obj) => { + obj.bringToFront() + }) + } + if (target.name === 'cell') { target.on('mousedown', () => { if (target.get('selected')) { @@ -135,6 +136,42 @@ export function useCanvas(id) { canvas?.renderAll() }) } + + if (target.name === 'lengthText') { + const x = target.left + const y = target.top + target.on('selected', (e) => { + Object.keys(target.controls).forEach((controlKey) => { + target.setControlVisible(controlKey, false) + }) + }) + target.on('moving', (e) => { + if (target.parentDirection === 'left' || target.parentDirection === 'right') { + const minX = target.minX + const maxX = target.maxX + + if (target.left <= minX) { + target.set({ left: minX, top: y }) + } else if (target.left >= maxX) { + target.set({ left: maxX, top: y }) + } else { + target.set({ top: y }) + } + } else if (target.parentDirection === 'top' || target.parentDirection === 'bottom') { + const minY = target.minY + const maxY = target.maxY + + if (target.top <= minY) { + target.set({ left: x, top: minY }) + } else if (target.top >= maxY) { + target.set({ left: x, top: maxY }) + } else { + target.set({ left: x }) + } + } + canvas?.renderAll() + }) + } } /** @@ -598,6 +635,10 @@ export function useCanvas(id) { 'lockScalingY', 'opacity', 'cells', + 'maxX', + 'maxY', + 'minX', + 'minY', ]) const str = JSON.stringify(objs)