지붕타입 지붕재, 지붕 배터리 추가

This commit is contained in:
hyojun.choi 2024-08-02 12:40:07 +09:00
parent 3a9ef49e4c
commit 8f051d541b
4 changed files with 113 additions and 57 deletions

View File

@ -6,7 +6,7 @@ import QRect from '@/components/fabric/QRect'
import RangeSlider from './ui/RangeSlider' import RangeSlider from './ui/RangeSlider'
import { useRecoilState, useRecoilValue } from 'recoil' 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 { QLine } from '@/components/fabric/QLine'
import { getCanvasState, insertCanvasState } from '@/lib/canvas' import { getCanvasState, insertCanvasState } from '@/lib/canvas'
import { calculateIntersection } from '@/util/canvas-util' import { calculateIntersection } from '@/util/canvas-util'
@ -31,7 +31,8 @@ export default function Roof2() {
const [showControl, setShowControl] = useState(false) const [showControl, setShowControl] = useState(false)
const roof = useRecoilValue(roofState) //
const roofMaterial = useRecoilValue(roofMaterialState)
const { const {
mode, mode,
@ -138,12 +139,12 @@ export default function Roof2() {
{ x: 100, y: 400 }, { x: 100, y: 400 },
] ]
const type2 = [ const type2 = [
{ x: 100, y: 100 }, { x: 200, y: 100 },
{ x: 100, y: 1000 }, { x: 200, y: 1000 },
{ x: 1000, y: 1000 }, { x: 1100, y: 1000 },
{ x: 1000, y: 600 }, { x: 1100, y: 600 },
{ x: 550, y: 600 }, { x: 650, y: 600 },
{ x: 550, y: 100 }, { x: 650, y: 100 },
] ]
const type3 = [ const type3 = [
@ -263,58 +264,17 @@ export default function Roof2() {
{ x: 675, y: 275 }, { x: 675, y: 275 },
{ x: 450, y: 850 }, { x: 450, y: 850 },
] ]
const polygon = new QPolygon(type4, { const polygon = new QPolygon(type2, {
fill: 'transparent', fill: 'transparent',
stroke: 'black', stroke: 'black',
strokeWidth: 1, strokeWidth: 1,
selectable: false, selectable: false,
fontSize: fontSize, fontSize: fontSize,
name: 'QPolygon1', name: 'wall',
}) })
canvas?.add(polygon) 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) 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) // const lines = togglePolygonLine(polygon)
// togglePolygonLine(lines[0]) // togglePolygonLine(lines[0])
} }
@ -404,6 +364,70 @@ export default function Roof2() {
handleClear() 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 내용 불러오기 * canvas 내용 불러오기
*/ */
@ -424,6 +448,21 @@ export default function Roof2() {
makeRoofPatternPolygon(roofStyle) 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 ( return (
<> <>
{canvas && ( {canvas && (
@ -530,6 +569,12 @@ export default function Roof2() {
<Button className="m-1 p-2" onClick={addCanvas}> <Button className="m-1 p-2" onClick={addCanvas}>
캔버스 추가 캔버스 추가
</Button> </Button>
<Button className="m-1 p-2" onClick={drawRoofMaterial}>
지붕타입 지붕재
</Button>
<Button className="m-1 p-2" onClick={createRoofRack}>
지붕가대
</Button>
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}> <Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`} canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
</Button> </Button>

View File

@ -234,7 +234,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
{ x: rectLeft, y: rectTop + rectHeight }, { x: rectLeft, y: rectTop + rectHeight },
{ x: rectLeft + rectWidth, y: rectTop + rectHeight }, { x: rectLeft + rectWidth, y: rectTop + rectHeight },
] ]
const allPointsInside = rectPoints.every((point) => this.inPolygon(point)) const allPointsInside = rectPoints.every((point) => this.inPolygon(point))
if (allPointsInside) { if (allPointsInside) {
@ -244,6 +243,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
width: rectWidth, width: rectWidth,
height: rectHeight, height: rectHeight,
fill: '#BFFD9F', fill: '#BFFD9F',
stroke: 'black',
selectable: true, // 선택 가능하게 설정 selectable: true, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금 lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금 lockMovementY: true, // Y 축 이동 잠금
@ -261,7 +261,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
return drawCellsArray return drawCellsArray
}, },
inPolygon(point) { inPolygon(point) {
const vertices = this.getCurrentPoints() const vertices = this.points
let intersects = 0 let intersects = 0
for (let i = 0; i < vertices.length; i++) { for (let i = 0; i < vertices.length; i++) {

View File

@ -60,3 +60,10 @@ export const drewRoofCellsState = atom({
default: [], default: [],
dangerouslyAllowMutability: true, 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,
})

View File

@ -499,6 +499,10 @@ export const dividePolygon = (polygon) => {
const startHip = hips.find((hip) => hip.startPoint.x === startPoint.x && hip.startPoint.y === startPoint.y) 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) 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) { if (startHip && endHip && startHip.endPoint.x === endHip.endPoint.x && startHip.endPoint.y === endHip.endPoint.y) {
polygonPoints.push(startHip.endPoint) polygonPoints.push(startHip.endPoint)
@ -506,7 +510,7 @@ export const dividePolygon = (polygon) => {
fontSize: polygon.fontSize, fontSize: polygon.fontSize,
id: polygon.id, id: polygon.id,
name: 'roof', name: 'roof',
selectable: true, selectable: false,
stroke: 'black', stroke: 'black',
fill: 'transparent', fill: 'transparent',
strokeWidth: 3, strokeWidth: 3,
@ -535,7 +539,7 @@ export const dividePolygon = (polygon) => {
fontSize: polygon.fontSize, fontSize: polygon.fontSize,
id: polygon.id, id: polygon.id,
name: 'roof', name: 'roof',
selectable: true, selectable: false,
stroke: 'black', stroke: 'black',
fill: 'transparent', fill: 'transparent',
strokeWidth: 3, strokeWidth: 3,
@ -553,7 +557,7 @@ export const dividePolygon = (polygon) => {
fontSize: polygon.fontSize, fontSize: polygon.fontSize,
id: polygon.id, id: polygon.id,
name: 'roof', name: 'roof',
selectable: true, selectable: false,
stroke: 'black', stroke: 'black',
fill: 'transparent', fill: 'transparent',
strokeWidth: 3, strokeWidth: 3,
@ -628,7 +632,7 @@ export const dividePolygon = (polygon) => {
fontSize: polygon.fontSize, fontSize: polygon.fontSize,
id: polygon.id, id: polygon.id,
name: 'roof', name: 'roof',
selectable: true, selectable: false,
stroke: 'black', stroke: 'black',
fill: 'transparent', fill: 'transparent',
strokeWidth: 3, strokeWidth: 3,