길이를 나타내는 text 움직임 범위 제한

This commit is contained in:
hyojun.choi 2024-08-22 10:47:54 +09:00
parent db333e06e0
commit eaed8ab15e
3 changed files with 94 additions and 25 deletions

View File

@ -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',
})

View File

@ -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',
})

View File

@ -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)