외벽선 편집 및 오프셋 작업중

This commit is contained in:
hyojun.choi 2024-10-08 18:25:14 +09:00
parent 1599f48e70
commit aaf32d4904
4 changed files with 310 additions and 30 deletions

View File

@ -3,14 +3,29 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useState } from 'react'
import WallLine from '@/components/floor-plan/modal/wallLineOffset/type/WallLine'
import Offset from '@/components/floor-plan/modal/wallLineOffset/type/Offset'
import { useWallLineOffsetSetting } from '@/hooks/roofcover/useWallLineOffsetSetting'
export default function WallLineOffsetSetting({ setShowWallLineOffsetSettingModal }) {
const { getMessage } = useMessage()
const { type, setType, buttonMenu, currentWallLineRef, TYPES, radioTypeRef, arrow1Ref, arrow2Ref, length1Ref, length2Ref, handleSave } =
useWallLineOffsetSetting()
const [buttonAct, setButtonAct] = useState(1)
const buttonMenu = [
{ id: 1, name: getMessage('modal.wallline.offset.setting.wallline.edit') },
{ id: 2, name: getMessage('modal.wallline.offset.setting.offset') },
]
const wallLineProps = {
length1Ref,
length2Ref,
arrow1Ref,
arrow2Ref,
radioTypeRef,
currentWallLineRef,
}
const offsetProps = {
length1Ref,
arrow1Ref,
currentWallLineRef,
}
return (
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
<div className={`modal-pop-wrap r`}>
@ -23,18 +38,20 @@ export default function WallLineOffsetSetting({ setShowWallLineOffsetSettingModa
<div className="modal-body">
<div className="modal-btn-wrap">
{buttonMenu.map((item) => (
<button key={item.id} className={`btn-frame modal ${buttonAct === item.id ? 'act' : ''}`} onClick={() => setButtonAct(item.id)}>
<button key={item.id} className={`btn-frame modal ${type === item.type ? 'act' : ''}`} onClick={() => setType(item.type)}>
{item.name}
</button>
))}
</div>
<div className="properties-setting-wrap outer">
<div className="setting-tit">{getMessage('setting')}</div>
{buttonAct === 1 && <WallLine />}
{buttonAct === 2 && <Offset />}
{type === TYPES.WALL_LINE_EDIT && <WallLine {...wallLineProps} />}
{type === TYPES.OFFSET && <Offset {...offsetProps} />}
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
<button className="btn-frame modal act" onClick={handleSave}>
{getMessage('modal.common.save')}
</button>
</div>
</div>
</div>

View File

@ -1,7 +1,67 @@
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
import { useEvent } from '@/hooks/useEvent'
export default function Offset({ setShowSlopeSettingModal }) {
export default function Offset({ length1Ref, arrow1Ref, currentWallLineRef }) {
const { getMessage } = useMessage()
const { addDocumentEventListener, initEvent } = useEvent()
useEffect(() => {
addDocumentEventListener('keydown', document, keyDown)
return () => {
initEvent()
}
}, [])
const handleBtnClick = (direction) => {
document.dispatchEvent(new KeyboardEvent('keydown', { key: direction }))
}
const [arrow, setArrow] = useState(null)
const keyDown = (e) => {
if (currentWallLineRef.current === null) {
alert('보조선을 먼저 선택하세요')
return
}
const direction = currentWallLineRef.current.direction
const key = e.key
switch (key) {
case 'Down': // IE/Edge
case 'ArrowDown': {
if (direction === 'left' || direction === 'right') {
setArrow('down')
arrow1Ref.current = 'down'
}
break
}
case 'Up': // IE/Edge
case 'ArrowUp':
if (direction === 'left' || direction === 'right') {
setArrow('up')
arrow1Ref.current = 'up'
}
break
case 'Left': // IE/Edge
case 'ArrowLeft':
if (direction === 'bottom' || direction === 'top') {
setArrow('left')
arrow1Ref.current = 'left'
}
break
case 'Right': // IE/Edge
case 'ArrowRight':
if (direction === 'bottom' || direction === 'top') {
setArrow('right')
arrow1Ref.current = 'right'
}
break
}
}
return (
<>
<div className="outline-wrap">
@ -13,7 +73,7 @@ export default function Offset({ setShowSlopeSettingModal }) {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} />
<input type="text" className="input-origin block" defaultValue={0} ref={length1Ref} />
</div>
<span className="thin">mm</span>
</div>
@ -24,10 +84,10 @@ export default function Offset({ setShowSlopeSettingModal }) {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="grid-direction">
<button className="direction up"></button>
<button className="direction down act"></button>
<button className="direction left"></button>
<button className="direction right"></button>
<button className={`direction up ${arrow === 'up' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowUp')}></button>
<button className={`direction down ${arrow === 'down' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowDown')}></button>
<button className={`direction left ${arrow === 'left' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowLeft')}></button>
<button className={`direction right ${arrow === 'right' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowRight')}></button>
</div>
</div>
</div>

View File

@ -1,17 +1,92 @@
import { useMessage } from '@/hooks/useMessage'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useEvent } from '@/hooks/useEvent'
export default function WallLine({ setShowSlopeSettingModal }) {
export default function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref, radioTypeRef, currentWallLineRef }) {
const { getMessage } = useMessage()
const [position1, setPosition1] = useState()
const [position2, setPosition2] = useState()
const { addDocumentEventListener, initEvent } = useEvent()
const [type, setType] = useState(1)
const [arrow1, setArrow1] = useState('up')
const [arrow2, setArrow2] = useState('up')
useEffect(() => {
addDocumentEventListener('keydown', document, keyDown)
return () => {
initEvent()
}
}, [])
const onChange = (e) => {
setType(Number(e.target.value))
radioTypeRef.current = e.target.value
}
const handleBtnClick = (direction) => {
document.dispatchEvent(new KeyboardEvent('keydown', { key: direction }))
}
const keyDown = (e) => {
if (currentWallLineRef.current === null) {
alert('보조선을 먼저 선택하세요')
return
}
const key = e.key
switch (key) {
case 'Down': // IE/Edge
case 'ArrowDown': {
if (radioTypeRef.current === '1') {
setArrow1('down')
arrow1Ref.current = 'down'
} else {
setArrow2('down')
arrow2Ref.current = 'down'
}
break
}
case 'Up': // IE/Edge
case 'ArrowUp':
if (radioTypeRef.current === '1') {
setArrow1('up')
arrow1Ref.current = 'up'
} else {
setArrow2('up')
arrow2Ref.current = 'up'
}
break
case 'Left': // IE/Edge
case 'ArrowLeft':
if (radioTypeRef.current === '1') {
setArrow1('left')
arrow1Ref.current = 'left'
} else {
setArrow2('left')
arrow2Ref.current = 'left'
}
break
case 'Right': // IE/Edge
case 'ArrowRight':
if (radioTypeRef.current === '1') {
setArrow1('right')
arrow1Ref.current = 'right'
} else {
setArrow2('right')
arrow2Ref.current = 'right'
}
break
}
}
return (
<>
<div className="outline-wrap">
<div className="guide sm">{getMessage('modal.wallline.offset.setting.wallline.edit.info')}</div>
<div className="discrimination-box mb10">
<div className="d-check-radio pop mb10">
<input type="radio" name="radio01" id="ra01" />
<input type="radio" name="radio01" id="ra01" value="1" checked={type === 1} onChange={(e) => onChange(e)} />
<label htmlFor="ra01">1{getMessage('modal.wallline.offset.setting.wallline.edit.position')}</label>
</div>
<div className="padding-form">
@ -21,7 +96,7 @@ export default function WallLine({ setShowSlopeSettingModal }) {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} />
<input type="text" className="input-origin block" defaultValue={0} readOnly={type !== 1} ref={length1Ref} />
</div>
<span className="thin">mm</span>
</div>
@ -32,10 +107,10 @@ export default function WallLine({ setShowSlopeSettingModal }) {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="grid-direction">
<button className="direction up"></button>
<button className="direction down act"></button>
<button className="direction left"></button>
<button className="direction right"></button>
<button className={`direction up ${arrow1 === 'up' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowUp')}></button>
<button className={`direction down ${arrow1 === 'down' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowDown')}></button>
<button className={`direction left ${arrow1 === 'left' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowLeft')}></button>
<button className={`direction right ${arrow1 === 'right' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowRight')}></button>
</div>
</div>
</div>
@ -45,7 +120,7 @@ export default function WallLine({ setShowSlopeSettingModal }) {
</div>
<div className="discrimination-box">
<div className="d-check-radio pop mb10">
<input type="radio" name="radio01" id="ra02" />
<input type="radio" name="radio01" id="ra02" value="2" checked={type === 2} onChange={(e) => onChange(e)} />
<label htmlFor="ra02">2{getMessage('modal.wallline.offset.setting.wallline.edit.position')}</label>
</div>
<div className="padding-form">
@ -55,7 +130,7 @@ export default function WallLine({ setShowSlopeSettingModal }) {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} />
<input type="text" className="input-origin block" defaultValue={0} readOnly={type !== 2} ref={length2Ref} />
</div>
<span className="thin">mm</span>
</div>
@ -66,10 +141,10 @@ export default function WallLine({ setShowSlopeSettingModal }) {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="grid-direction">
<button className="direction up"></button>
<button className="direction down act"></button>
<button className="direction left"></button>
<button className="direction right"></button>
<button className={`direction up ${arrow2 === 'up' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowUp')}></button>
<button className={`direction down ${arrow2 === 'down' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowDown')}></button>
<button className={`direction left ${arrow2 === 'left' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowLeft')}></button>
<button className={`direction right ${arrow2 === 'right' ? 'act' : ''} `} onClick={() => handleBtnClick('ArrowRight')}></button>
</div>
</div>
</div>

View File

@ -0,0 +1,128 @@
import { canvasState } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil'
import { useEffect, useRef, useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { useEvent } from '@/hooks/useEvent'
import { useLine } from '@/hooks/useLine'
export function useWallLineOffsetSetting() {
const canvas = useRecoilValue(canvasState)
const { showLine, addLine } = useLine()
const { getMessage } = useMessage()
const { addCanvasMouseEventListener, initEvent } = useEvent()
const length1Ref = useRef(null)
const length2Ref = useRef(null)
const radioTypeRef = useRef('1')
const currentWallLineRef = useRef(null)
const arrow1Ref = useRef(null)
const arrow2Ref = useRef(null)
const TYPES = {
WALL_LINE_EDIT: 'wallLineEdit',
OFFSET: 'offset',
}
const buttonMenu = [
{ id: 1, name: getMessage('modal.wallline.offset.setting.wallline.edit'), type: TYPES.WALL_LINE_EDIT },
{ id: 2, name: getMessage('modal.wallline.offset.setting.offset'), type: TYPES.OFFSET },
]
const [type, setType] = useState(TYPES.WALL_LINE_EDIT)
useEffect(() => {
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
outerLines.forEach((outerLine) => {
outerLine.set({ selectable: true })
showLine(outerLine)
})
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
roofs.forEach((roof) => {
roof.innerLines.forEach((innerLine) => {
canvas.remove(innerLine)
})
canvas.remove(roof)
})
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
wallLines.forEach((wallLine) => {
canvas.remove(wallLine)
})
addCanvasMouseEventListener('mouse:down', mouseDown)
return () => {
canvas.discardActiveObject()
initEvent()
}
}, [])
const mouseDown = (e) => {
if (!e.target || (e.target && e.target.name !== 'outerLine')) {
return
}
currentWallLineRef.current = e.target
}
const handleSave = () => {
switch (type) {
case TYPES.WALL_LINE_EDIT:
handleWallLineEditSave()
break
case TYPES.OFFSET:
handleOffsetSave()
break
}
}
const handleWallLineEditSave = () => {
const direction = currentWallLineRef.current.direction
let canDirections = direction === 'left' || direction === 'right' ? ['up', 'down'] : ['left', 'right']
if (radioTypeRef === 1) {
if (!canDirections.includes(arrow1Ref.current)) {
alert('방향을 다시 선택하세요')
return
}
} else {
if (!canDirections.includes(arrow2Ref.current)) {
alert('방향을 다시 선택하세요')
return
}
}
}
const handleOffsetSave = () => {
const direction = currentWallLineRef.current.direction
let canDirections = direction === 'left' || direction === 'right' ? ['up', 'down'] : ['left', 'right']
if (!canDirections.includes(arrow1Ref.current)) {
alert('방향을 다시 선택하세요')
return
}
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
const idx = currentWallLineRef.current.idx
const prevLine = outerLines.find((line) => (line.idx === idx - 1 < 0 ? outerLines.length - 1 : idx - 1))
const currentLine = currentWallLineRef.current
const nextLine = outerLines.find((line) => (line.idx === idx + 1 > outerLines.length - 1 ? 0 : idx + 1))
switch (arrow1Ref.current) {
case 'up': {
console.log(prevLine, currentLine, nextLine)
break
}
case 'down': {
break
}
case 'left': {
break
}
case 'right': {
break
}
}
}
return { type, setType, buttonMenu, TYPES, length1Ref, length2Ref, radioTypeRef, currentWallLineRef, arrow1Ref, arrow2Ref, handleSave }
}