From 4a16fcbf3d88dcd1943985739416a357409e5505 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 5 Jul 2024 09:27:12 +0900 Subject: [PATCH] =?UTF-8?q?QPolygon=20group=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 10 +- src/components/fabric/QPolygon.js | 221 ++++++++++++++--------------- src/components/fabric/QPolygon2.js | 79 ----------- src/hooks/useMode.js | 19 ++- 4 files changed, 128 insertions(+), 201 deletions(-) delete mode 100644 src/components/fabric/QPolygon2.js diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 496d6639..f17612a6 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -4,10 +4,10 @@ import { Mode, useMode } from '@/hooks/useMode' import QRect from '@/components/fabric/QRect' import QLine from '@/components/fabric/QLine' import QPolygon from '@/components/fabric/QPolygon' -import QPolygon2 from '@/components/fabric/QPolygon2' + import RangeSlider from './ui/RangeSlider' import { useRecoilState } from 'recoil' -import { fontSizeState, canvasSizeState } from '@/store/canvasAtom' +import { canvasSizeState, fontSizeState } from '@/store/canvasAtom' export default function Roof2() { const { @@ -89,12 +89,13 @@ export default function Roof2() { selectable: true, fontSize: fontSize, }, + canvas, ) canvas?.add(polygon) console.log(polygon) - // polygon.fillCell({ width: 50, height: 30, padding: 10 }) + polygon.fillCell({ width: 50, height: 30, padding: 10 }) } } @@ -139,6 +140,7 @@ export default function Roof2() { selectable: true, fontSize: fontSize, }, + canvas, ) canvas?.add(polygon) @@ -162,7 +164,7 @@ export default function Roof2() { const makeQPolygon2 = () => { if (canvas) { - const polygon2 = new QPolygon2( + const polygon2 = new QPolygon( [ { x: 100, y: 100 }, { x: 800, y: 100 }, diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index ab7a7171..c7dcf53c 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -1,87 +1,63 @@ import { fabric } from 'fabric' import { distanceBetweenPoints } from '@/util/canvas-util' -export default class QPolygon extends fabric.Polygon { - #viewLengthText - #text = [] - #fontSize - type = 'QPolygon' - constructor(points, option) { - if (!option.fontSize) { +export default class QPolygon extends fabric.Group { + type = 'QPolygon' + polygon + points + texts = [] + canvas + fontSize + constructor(points, options, canvas) { + if (!options.fontSize) { throw new Error('Font size is required.') } - super(points, option) - this.#fontSize = option.fontSize - this.#init(points) - this.#addControl() + if (!canvas) { + throw new Error('Canvas is required.') + } + + const polygon = new fabric.Polygon(points, options) + super([polygon], {}) + this.fontSize = options.fontSize + this.points = points + this.polygon = polygon + this.canvas = canvas + + this.#init() + this.#addEvent() } - #init(points) { - this.#viewLengthText = points.viewLengthText ?? true - } - - setViewLengthText(bool) { - this.#viewLengthText = bool + #init() { this.#addLengthText() } - #addControl() { - this.on('removed', () => { - if (this.#text.length > 0) { - this.#text.forEach((text) => { - this.canvas.remove(text) - }) - this.#text = [] - } - }) - - this.on('added', () => { - this.#addLengthText() - }) - - this.on('modified', (e) => { - console.log(this) - this.#addLengthText() - }) - + #addEvent() { this.on('scaling', (e) => { - this.#addLengthText() - }) - - this.on('moving', () => { - this.#addLengthText() + this.#updateLengthText() }) } - setTexts(texts) { - this.#text = texts - } - - getTexts() { - return this.#text + setFontSize(fontSize) { + this.texts.forEach((text) => { + text.set({ fontSize }) + this.canvas.requestRenderAll() + }) + this.fontSize = fontSize } #addLengthText() { - if (this.#text.length > 0) { - this.#text.forEach((text) => { + if (this.texts.length > 0) { + this.texts.forEach((text) => { this.canvas.remove(text) }) - this.#text = [] + this.texts = [] } - if (!this.#viewLengthText) { - return - } - - const scaleX = this.scaleX - const scaleY = this.scaleY - const points = this.getCurrentPoints() - for (let i = 0; i < points.length; i++) { - const start = points[i] + points.forEach((start, i) => { const end = points[(i + 1) % points.length] - const dx = (end.x - start.x) * scaleX - const dy = (end.y - start.y) * scaleY + const dx = end.x - start.x + const dy = end.y - start.y const length = Math.sqrt(dx * dx + dy * dy) const midPoint = new fabric.Point( @@ -89,69 +65,39 @@ export default class QPolygon extends fabric.Polygon { (start.y + end.y) / 2, ) + // Create new text object if it doesn't exist const text = new fabric.Text(length.toFixed(0), { left: midPoint.x, top: midPoint.y, - fontSize: this.#fontSize, + fontSize: this.fontSize, selectable: false, }) - this.#text.push(text) - this.canvas.add(text) - } - } - setFontSize(fontSize) { - this.#fontSize = fontSize - this.#addLengthText() - } - - getCurrentPoints() { - const scaleX = this.scaleX - const scaleY = this.scaleY - - return this.points.map((point) => { - return { - x: point.x * scaleX + this.left, - y: point.y * scaleY + this.top, - } + this.texts.push(text) + this.addWithUpdate(text) }) + + this.canvas.renderAll() } - #distanceFromEdge(point) { - const vertices = this.points - let minDistance = Infinity + #updateLengthText() { + const points = this.getCurrentPoints() - for (let i = 0; i < vertices.length; i++) { - let vertex1 = vertices[i] - let vertex2 = vertices[(i + 1) % vertices.length] + points.forEach((start, 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) - const dx = vertex2.x - vertex1.x - const dy = vertex2.y - vertex1.y + // Update the text object with the new length + this.texts[i].set({ text: length.toFixed(0) }) + }) - const t = - ((point.x - vertex1.x) * dx + (point.y - vertex1.y) * dy) / - (dx * dx + dy * dy) - - let closestPoint - if (t < 0) { - closestPoint = vertex1 - } else if (t > 1) { - closestPoint = vertex2 - } else { - closestPoint = new fabric.Point(vertex1.x + t * dx, vertex1.y + t * dy) - } - - const distance = distanceBetweenPoints(point, closestPoint) - if (distance < minDistance) { - minDistance = distance - } - } - - return minDistance + this.canvas.renderAll() } fillCell(cell = { width: 50, height: 100, padding: 10 }) { - const points = this.points + const points = this.getCurrentPoints() let bounds try { @@ -195,7 +141,7 @@ export default class QPolygon extends fabric.Polygon { ) if (isInside) { - this.canvas.add(rect) + this.addWithUpdate(rect) } } } @@ -204,7 +150,7 @@ export default class QPolygon extends fabric.Polygon { } inPolygon(point) { - const vertices = this.points + const vertices = this.getCurrentPoints() let intersects = 0 for (let i = 0; i < vertices.length; i++) { @@ -236,4 +182,57 @@ export default class QPolygon extends fabric.Polygon { return intersects % 2 === 1 } + + #distanceFromEdge(point) { + const vertices = this.getCurrentPoints() + let minDistance = Infinity + + for (let i = 0; i < vertices.length; i++) { + let vertex1 = vertices[i] + let vertex2 = vertices[(i + 1) % vertices.length] + + const dx = vertex2.x - vertex1.x + const dy = vertex2.y - vertex1.y + + const t = + ((point.x - vertex1.x) * dx + (point.y - vertex1.y) * dy) / + (dx * dx + dy * dy) + + let closestPoint + if (t < 0) { + closestPoint = vertex1 + } else if (t > 1) { + closestPoint = vertex2 + } else { + closestPoint = new fabric.Point(vertex1.x + t * dx, vertex1.y + t * dy) + } + + const distance = distanceBetweenPoints(point, closestPoint) + if (distance < minDistance) { + minDistance = distance + } + } + + return minDistance + } + + setViewLengthText(boolean) { + this.texts.forEach((text) => { + text.visible = boolean + }) + + this.canvas.renderAll() + } + + getCurrentPoints() { + const scaleX = this.scaleX + const scaleY = this.scaleY + + return this.points.map((point) => { + return { + x: point.x * scaleX, + y: point.y * scaleY, + } + }) + } } diff --git a/src/components/fabric/QPolygon2.js b/src/components/fabric/QPolygon2.js deleted file mode 100644 index b59356c6..00000000 --- a/src/components/fabric/QPolygon2.js +++ /dev/null @@ -1,79 +0,0 @@ -import { fabric } from 'fabric' - -export default class QPolygon2 extends fabric.Group { - type = 'QPolygon2' - polygon - points - texts = [] - canvas - constructor(points, options, canvas) { - const polygon = new fabric.Polygon(points, options) - super([polygon], {}) - this.points = points - this.polygon = polygon - this.canvas = canvas - - this.#init() - this.#addEvent() - } - - #init() { - this.#addLengthText() - } - - #addEvent() { - this.on('modified', () => { - // this.#addLengthText() - }) - } - - #addLengthText() { - const points = this.getCurrentPoints() - - points.forEach((start, 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) - - const midPoint = new fabric.Point( - (start.x + end.x) / 2, - (start.y + end.y) / 2, - ) - - if (this.texts[i]) { - // Update existing text - this.texts[i].set({ - text: length.toFixed(0), - left: midPoint.x, - top: midPoint.y, - }) - } else { - // Create new text object if it doesn't exist - const text = new fabric.Text(length.toFixed(0), { - left: midPoint.x, - top: midPoint.y, - fontSize: 16, - selectable: false, - }) - - this.texts.push(text) - this.addWithUpdate(text) - } - }) - - this.canvas.renderAll() - } - - getCurrentPoints() { - const scaleX = this.scaleX - const scaleY = this.scaleY - - return this.points.map((point) => { - return { - x: point.x * scaleX, - y: point.y * scaleY, - } - }) - } -} diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 88d50d4a..2016cb81 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -405,13 +405,17 @@ export function useMode() { }) // 점 배열을 사용하여 새로운 다각형 객체를 생성합니다. - const polygon = new QPolygon(points, { - stroke: 'black', - fill: 'transparent', - viewLengthText: true, - selectable: true, - fontSize: fontSize, - }) + const polygon = new QPolygon( + points, + { + stroke: 'black', + fill: 'transparent', + viewLengthText: true, + selectable: true, + fontSize: fontSize, + }, + canvas, + ) // 새로운 다각형 객체를 캔버스에 추가합니다. canvas.add(polygon) @@ -421,6 +425,7 @@ export function useMode() { polygon.fillCell() canvas.renderAll() polygon.setViewLengthText(false) + setMode(Mode.DEFAULT) } }