From 8f051d541bbf541f57ed8b3d74fa1788f273a098 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 2 Aug 2024 12:40:07 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A7=80=EB=B6=95=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=A7=80=EB=B6=95=EC=9E=AC,=20=EC=A7=80=EB=B6=95=20=EB=B0=B0?= =?UTF-8?q?=ED=84=B0=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 147 +++++++++++++++++++----------- src/components/fabric/QPolygon.js | 4 +- src/store/canvasAtom.js | 7 ++ src/util/qpolygon-utils.js | 12 ++- 4 files changed, 113 insertions(+), 57 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 8d2fc35b..da41280b 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -6,7 +6,7 @@ import QRect from '@/components/fabric/QRect' import RangeSlider from './ui/RangeSlider' import { useRecoilState, useRecoilValue } from 'recoil' -import { canvasSizeState, fontSizeState, roofState, sortedPolygonArray } from '@/store/canvasAtom' +import { canvasSizeState, fontSizeState, roofMaterialState, roofState, sortedPolygonArray } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' import { getCanvasState, insertCanvasState } from '@/lib/canvas' import { calculateIntersection } from '@/util/canvas-util' @@ -31,7 +31,8 @@ export default function Roof2() { const [showControl, setShowControl] = useState(false) - const roof = useRecoilValue(roofState) + //지붕재 + const roofMaterial = useRecoilValue(roofMaterialState) const { mode, @@ -138,12 +139,12 @@ export default function Roof2() { { x: 100, y: 400 }, ] const type2 = [ - { x: 100, y: 100 }, - { x: 100, y: 1000 }, - { x: 1000, y: 1000 }, - { x: 1000, y: 600 }, - { x: 550, y: 600 }, - { x: 550, y: 100 }, + { x: 200, y: 100 }, + { x: 200, y: 1000 }, + { x: 1100, y: 1000 }, + { x: 1100, y: 600 }, + { x: 650, y: 600 }, + { x: 650, y: 100 }, ] const type3 = [ @@ -263,58 +264,17 @@ export default function Roof2() { { x: 675, y: 275 }, { x: 450, y: 850 }, ] - const polygon = new QPolygon(type4, { + const polygon = new QPolygon(type2, { fill: 'transparent', stroke: 'black', strokeWidth: 1, selectable: false, fontSize: fontSize, - name: 'QPolygon1', + name: 'wall', }) canvas?.add(polygon) - - polygon.set('strokeDashArray', [10, 5, 2, 5]) - polygon.set('stroke', 'blue') - polygon.set('strokeWidth', 1) - - // const newPolygon = fabric.util.clone(polygon) - handleOuterlinesTest2(polygon) - - const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') - - roofs.forEach((roof) => { - let maxLengthLine = roof.lines.reduce((acc, cur) => { - return acc.length > cur.length ? acc : cur - }) - - // 패턴 소스를 위한 임시 캔버스 생성 - const patternSourceCanvas = document.createElement('canvas') - if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { - patternSourceCanvas.width = 20 * window.devicePixelRatio || 1 - patternSourceCanvas.height = 10 * window.devicePixelRatio || 1 - } else { - patternSourceCanvas.width = 10 * window.devicePixelRatio || 1 - patternSourceCanvas.height = 20 * window.devicePixelRatio || 1 - } - - const ctx = patternSourceCanvas.getContext('2d') - - // 벽돌 패턴 그리기 - ctx.scale(window.devicePixelRatio || 1, window.devicePixelRatio || 1) - ctx.strokeStyle = 'green' - ctx.lineWidth = 0.4 - ctx.strokeRect(0, 0, 100, 100) - // 패턴 생성 - const pattern = new fabric.Pattern({ - source: patternSourceCanvas, - repeat: 'repeat', - }) - - roof.set('fill', pattern) - }) - // const lines = togglePolygonLine(polygon) // togglePolygonLine(lines[0]) } @@ -404,6 +364,70 @@ export default function Roof2() { handleClear() } + const drawRoofMaterial = () => { + const { width, height, roofStyle } = roofMaterial + + const wallPolygon = canvas?.getObjects().find((obj) => obj.name === 'wall') + + wallPolygon.set('strokeDashArray', [10, 5, 2, 5]) + wallPolygon.set('stroke', 'blue') + wallPolygon.set('strokeWidth', 1) + + const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') + + roofs.forEach((roof) => { + let maxLengthLine = roof.lines.reduce((acc, cur) => { + return acc.length > cur.length ? acc : cur + }) + + const roofRatio = window.devicePixelRatio || 1 + + // 패턴 소스를 위한 임시 캔버스 생성 + const patternSourceCanvas = document.createElement('canvas') + if (roofStyle === 1) { + if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { + patternSourceCanvas.width = width * roofRatio + patternSourceCanvas.height = height * roofRatio + } else { + patternSourceCanvas.width = height * roofRatio + patternSourceCanvas.height = width * roofRatio + } + } else if (roofStyle === 2) { + if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { + patternSourceCanvas.width = width * 2 + patternSourceCanvas.height = height * 2 + } else { + patternSourceCanvas.width = height * 2 + patternSourceCanvas.height = width * 2 + } + } + + const ctx = patternSourceCanvas.getContext('2d') + + ctx.scale(roofRatio, roofRatio) + ctx.strokeStyle = 'green' + ctx.lineWidth = 0.4 + // 벽돌 패턴 그리기 + if (roofStyle === 1) { + ctx.strokeRect(0, 0, 50, 30) + } else if (roofStyle === 2) { + // 지그재그 + ctx.strokeRect(0, 0, 200, 100) + ctx.strokeRect(100, 100, 200, 100) + } + + // 패턴 생성 + const pattern = new fabric.Pattern({ + source: patternSourceCanvas, + repeat: 'repeat', + }) + roof.set('fill', null) + + roof.set('fill', pattern) + canvas?.renderAll() + }) + } + /** * canvas 내용 불러오기 */ @@ -424,6 +448,21 @@ export default function Roof2() { makeRoofPatternPolygon(roofStyle) } + const createRoofRack = () => { + const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') + roofs.forEach((roof) => { + let maxLengthLine = roof.lines.reduce((acc, cur) => { + return acc.length > cur.length ? acc : cur + }) + + if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { + roof.fillCell({ width: 50, height: 100, padding: 0 }) + } else { + roof.fillCell({ width: 100, height: 50, padding: 0 }) + } + }) + } + return ( <> {canvas && ( @@ -530,6 +569,12 @@ export default function Roof2() { + + diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index f67c0e68..685d83ee 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -234,7 +234,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { { x: rectLeft, y: rectTop + rectHeight }, { x: rectLeft + rectWidth, y: rectTop + rectHeight }, ] - const allPointsInside = rectPoints.every((point) => this.inPolygon(point)) if (allPointsInside) { @@ -244,6 +243,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { width: rectWidth, height: rectHeight, fill: '#BFFD9F', + stroke: 'black', selectable: true, // 선택 가능하게 설정 lockMovementX: true, // X 축 이동 잠금 lockMovementY: true, // Y 축 이동 잠금 @@ -261,7 +261,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { return drawCellsArray }, inPolygon(point) { - const vertices = this.getCurrentPoints() + const vertices = this.points let intersects = 0 for (let i = 0; i < vertices.length; i++) { diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 6491dc2d..48eb0281 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -60,3 +60,10 @@ export const drewRoofCellsState = atom({ default: [], dangerouslyAllowMutability: true, }) + +// 지붕재 width, height, rafter(서까래), roofStyle을 갖고있고 roofStyle 1은 정방향, 2는 지그재그 +export const roofMaterialState = atom({ + key: 'roofMaterial', + default: { width: 20, height: 10, rafter: 0, roofStyle: 2 }, + dangerouslyAllowMutability: true, +}) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 078303d0..36eadd4d 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -499,6 +499,10 @@ export const dividePolygon = (polygon) => { const startHip = hips.find((hip) => hip.startPoint.x === startPoint.x && hip.startPoint.y === startPoint.y) const endHip = hips.find((hip) => hip.startPoint.x === endPoint.x && hip.startPoint.y === endPoint.y) + if (!startHip || !endHip) { + return + } + if (startHip && endHip && startHip.endPoint.x === endHip.endPoint.x && startHip.endPoint.y === endHip.endPoint.y) { polygonPoints.push(startHip.endPoint) @@ -506,7 +510,7 @@ export const dividePolygon = (polygon) => { fontSize: polygon.fontSize, id: polygon.id, name: 'roof', - selectable: true, + selectable: false, stroke: 'black', fill: 'transparent', strokeWidth: 3, @@ -535,7 +539,7 @@ export const dividePolygon = (polygon) => { fontSize: polygon.fontSize, id: polygon.id, name: 'roof', - selectable: true, + selectable: false, stroke: 'black', fill: 'transparent', strokeWidth: 3, @@ -553,7 +557,7 @@ export const dividePolygon = (polygon) => { fontSize: polygon.fontSize, id: polygon.id, name: 'roof', - selectable: true, + selectable: false, stroke: 'black', fill: 'transparent', strokeWidth: 3, @@ -628,7 +632,7 @@ export const dividePolygon = (polygon) => { fontSize: polygon.fontSize, id: polygon.id, name: 'roof', - selectable: true, + selectable: false, stroke: 'black', fill: 'transparent', strokeWidth: 3,