지붕타입 지붕재, 지붕 배터리 추가
This commit is contained in:
parent
3a9ef49e4c
commit
8f051d541b
@ -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() {
|
||||
<Button className="m-1 p-2" onClick={addCanvas}>
|
||||
캔버스 추가
|
||||
</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}>
|
||||
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
||||
</Button>
|
||||
|
||||
@ -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++) {
|
||||
|
||||
@ -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,
|
||||
})
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user