Merge branch 'dev' into dev-ds

This commit is contained in:
Daseul Kim 2024-09-30 16:31:02 +09:00
commit ee91d65c85
17 changed files with 1054 additions and 193 deletions

View File

@ -53,8 +53,9 @@ export const Mode = {
export const LINE_TYPE = { export const LINE_TYPE = {
WALLLINE: { WALLLINE: {
/** /**
* 처마 / 캐라바 / / 팔작지붕 / 반절처 / 한쪽흐름 * 없음 / 처마 / 캐라바 / / 팔작지붕 / 반절처 / 한쪽흐름
*/ */
DEFAULT: 'default',
EAVES: 'eaves', EAVES: 'eaves',
GABLE: 'gable', GABLE: 'gable',
WALL: 'wall', WALL: 'wall',

View File

@ -34,6 +34,7 @@ export default function FloorPlan() {
const outlineProps = { const outlineProps = {
setShowOutlineModal, setShowOutlineModal,
setShowPropertiesSettingModal,
} }
const modalProps = { const modalProps = {

View File

@ -1,8 +1,11 @@
import Image from 'next/image' import Image from 'next/image'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
export default function Angle() { export default function Angle({ props }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { angle1, setAngle1, angle1Ref, length1, setLength1, length1Ref } = props
return ( return (
<> <>
<div className="outline-wrap"> <div className="outline-wrap">
@ -11,16 +14,40 @@ export default function Angle() {
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.angle')}</span> <span className="mr10">{getMessage('modal.cover.outline.angle')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={4} /> <input
type="text"
className="input-origin block"
value={angle1}
ref={angle1Ref}
onChange={(e) => onlyNumberWithDotInputChange(e, setAngle1)}
placeholder="45"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={(e) => {
setAngle1(0)
}}
></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.arrow')}</span> <span className="mr10">{getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={5000} /> <input
type="text"
className="input-origin block"
value={length1}
ref={length1Ref}
onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setLength1(0)
}}
></button>
</div> </div>
</div> </div>
<div className="cul-box"> <div className="cul-box">

View File

@ -1,7 +1,24 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange } from '@/util/input-utils'
export default function Diagonal() { export default function Diagonal({ props }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const {
length1,
setLength1,
length1Ref,
length2,
setLength2,
length2Ref,
outerLineDiagonalLength,
setOuterLineDiagonalLength,
outerLineDiagonalLengthRef,
arrow1,
setArrow1,
arrow2,
setArrow2,
} = props
return ( return (
<> <>
<div className="outline-wrap"> <div className="outline-wrap">
@ -13,26 +30,77 @@ export default function Diagonal() {
{getMessage('modal.cover.outline.length')} {getMessage('modal.cover.outline.length')}
</span> </span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={1000} /> <input
type="text"
className="input-origin block"
value={outerLineDiagonalLength}
ref={outerLineDiagonalLengthRef}
onChange={(e) => onlyNumberInputChange(e, setOuterLineDiagonalLength)}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setOuterLineDiagonalLength(0)
}}
></button>
</div> </div>
</div> </div>
<div className="outline-inner"> <div className="outline-inner">
<div className="outline-form"> <div className="outline-form">
<span className="mr10"> {getMessage('modal.cover.outline.length')}</span> <span className="mr10"> {getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={5000} /> <input
type="text"
className="input-origin block"
value={length1}
ref={length1Ref}
onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setLength1(0)
setLength2(0)
setArrow1('')
setArrow2('')
}}
></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span> {getMessage('modal.cover.outline.arrow')}</span> <span> {getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className="direction up"></button> <button
<button className="direction down act"></button> className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
<button className="direction left"></button> onClick={() => {
<button className="direction right"></button> setArrow1('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow1('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow1 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow1('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow1 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow1('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>
@ -40,16 +108,48 @@ export default function Diagonal() {
<div className="outline-form"> <div className="outline-form">
<span className="mr10"> {getMessage('modal.cover.outline.length')}</span> <span className="mr10"> {getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '98px' }}> <div className="input-grid" style={{ width: '98px' }}>
<input type="text" className="input-origin block" defaultValue={8000} /> <input
type="text"
className="input-origin block"
value={length2}
ref={length2Ref}
onChange={(e) => onlyNumberInputChange(e, setLength2)}
readOnly={true}
placeholder="3000"
/>
</div> </div>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span> {getMessage('modal.cover.outline.arrow')}</span> <span> {getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className="direction up"></button> <button
<button className="direction down act"></button> className={`direction up ${arrow2 === '↑' ? 'act' : ''}`}
<button className="direction left"></button> onClick={() => {
<button className="direction right"></button> setArrow2('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow2 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow2('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow2('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow2('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,48 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
import { getDegreeByChon } from '@/util/canvas-util'
export default function DoublePitch() { export default function DoublePitch({ props }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const {
angle1,
setAngle1,
angle1Ref,
angle2,
setAngle2,
angle2Ref,
length1,
setLength1,
length1Ref,
length2,
setLength2,
length2Ref,
arrow1,
setArrow1,
arrow2,
setArrow2,
arrow1Ref,
arrow2Ref,
} = props
const getLength2 = () => {
const angle1Value = angle1Ref.current.value
const angle2Value = angle2Ref.current.value
const length1Value = length1Ref.current.value
const arrow1Value = arrow1Ref.current
const arrow2Value = arrow2Ref.current
if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '') {
const radian1 = (getDegreeByChon(angle1Value) * Math.PI) / 180
const radian2 = (getDegreeByChon(angle2Value) * Math.PI) / 180
return Math.floor((Math.tan(radian1) * length1Value) / Math.tan(radian2))
}
return 0
}
return ( return (
<> <>
<div className="outline-wrap"> <div className="outline-wrap">
@ -9,26 +50,70 @@ export default function DoublePitch() {
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.angle')}</span> <span className="mr10">{getMessage('modal.cover.outline.angle')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={4} /> <input
type="text"
className="input-origin block"
value={angle1}
ref={angle1Ref}
onChange={(e) => onlyNumberWithDotInputChange(e, setAngle1)}
placeholder="45"
/>
</div> </div>
<button className="reset-btn"></button> <button className="reset-btn" onClick={() => setAngle1(0)}></button>
</div> </div>
</div> </div>
<div className="outline-inner"> <div className="outline-inner">
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.length')}</span> <span className="mr10">{getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={5000} /> <input
type="text"
className="input-origin block"
value={length1}
ref={length1Ref}
onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setLength1(0)
setArrow1('')
}}
></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span>{getMessage('modal.cover.outline.arrow')}</span> <span>{getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className="direction up"></button> <button
<button className="direction down act"></button> className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
<button className="direction left"></button> onClick={() => {
<button className="direction right"></button> setArrow1('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow1('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow1 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow1('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow1 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow1('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>
@ -38,26 +123,80 @@ export default function DoublePitch() {
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.angle')}</span> <span className="mr10">{getMessage('modal.cover.outline.angle')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={6} /> <input
type="text"
className="input-origin block"
value={angle2}
ref={angle2Ref}
onChange={(e) => {
onlyNumberWithDotInputChange(e, setAngle2)
console.log(getLength2())
setLength2(getLength2())
}}
placeholder="45"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setAngle2(0)
}}
></button>
</div> </div>
</div> </div>
<div className="outline-inner"> <div className="outline-inner">
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.length')}</span> <span className="mr10">{getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={3000} /> <input
type="text"
className="input-origin block"
value={length2}
ref={length2Ref}
onChange={(e) => onlyNumberInputChange(e, setLength2)}
readOnly={true}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setLength2(0)
setArrow2('')
}}
></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span>{getMessage('modal.cover.outline.arrow')}</span> <span>{getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className="direction up"></button> <button
<button className="direction down act"></button> className={`direction up ${arrow2 === '↑' ? 'act' : ''}`}
<button className="direction left"></button> onClick={() => {
<button className="direction right"></button> setArrow2('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow2 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow2('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow2('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow2('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,12 +1,12 @@
'use client' 'use client'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall'
import { onlyNumberInputChange } from '@/util/input-utils' import { onlyNumberInputChange } from '@/util/input-utils'
export default function OuterLineWall(props) { export default function OuterLineWall({ props }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { length1, setLength1, length1Ref, arrow1, setArrow1 } = useOuterLineWall()
const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props
return ( return (
<div className="outline-wrap"> <div className="outline-wrap">
<div className="outline-inner"> <div className="outline-inner">
@ -22,15 +22,39 @@ export default function OuterLineWall(props) {
placeholder="3000" placeholder="3000"
/> />
</div> </div>
<button className="reset-btn"></button> <button className="reset-btn" onClick={() => setLength1(0)}></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span>{getMessage('modal.cover.outline.arrow')}</span> <span>{getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className={`direction up ${arrow1 === '↑' ? 'act' : ''}`} onClick={() => setArrow1('↑')}></button> <button
<button className={`direction down ${arrow1 === '↓' ? 'act' : ''}`} onClick={() => setArrow1('↓')}></button> className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
<button className={`direction left ${arrow1 === '←' ? 'act' : ''}`} onClick={() => setArrow1('←')}></button> onClick={() => {
<button className={`direction right ${arrow1 === '→' ? 'act' : ''}`} onClick={() => setArrow1('→')}></button> setArrow1('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow1('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow1 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow1('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow1 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow1('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,34 +0,0 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useMessage } from '@/hooks/useMessage'
export default function PropertiesSetting(props) {
const { getMessage } = useMessage()
const { setShowPropertiesSettingModal } = props
return (
<WithDraggable isShow={true}>
<div className={`modal-pop-wrap ssm`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.canvas.setting.wallline.properties.setting')}</h1>
<button className="modal-close" onClick={() => setShowPropertiesSettingModal(false)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="properties-guide">{getMessage('modal.canvas.setting.wallline.properties.setting.info')}</div>
<div className="properties-setting-wrap">
<div className="setting-tit">{getMessage('setting')}</div>
<div className="setting-btn-wrap">
<button className="setting-btn green mr5">{getMessage('modal.canvas.setting.wallline.properties.setting.eaves')}</button>
<button className="setting-btn blue">{getMessage('modal.canvas.setting.wallline.properties.setting.edge')}</button>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal mr5">{getMessage('modal.cover.outline.rollback')}</button>
<button className="btn-frame modal act">{getMessage('modal.cover.outline.finish')}</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,56 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useMessage } from '@/hooks/useMessage'
import { usePropertiesSetting } from '@/hooks/roofcover/usePropertiesSetting'
export default function PropertiesSetting(props) {
const { getMessage } = useMessage()
const { setShowPropertiesSettingModal } = props
const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting()
return (
<WithDraggable isShow={true}>
<div className={`modal-pop-wrap ssm`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.canvas.setting.wallline.properties.setting')}</h1>
<button
className="modal-close"
onClick={() => {
closeModal(setShowPropertiesSettingModal)
}}
>
닫기
</button>
</div>
<div className="modal-body">
<div className="properties-guide">{getMessage('modal.canvas.setting.wallline.properties.setting.info')}</div>
<div className="properties-setting-wrap">
<div className="setting-tit">{getMessage('setting')}</div>
<div className="setting-btn-wrap">
<button className="setting-btn green mr5" onClick={handleSetEaves}>
{getMessage('modal.canvas.setting.wallline.properties.setting.eaves')}
</button>
<button className="setting-btn blue" onClick={handleSetGable}>
{getMessage('modal.canvas.setting.wallline.properties.setting.edge')}
</button>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal mr5" onClick={handleRollback}>
{getMessage('modal.cover.outline.rollback')}
</button>
<button
className="btn-frame modal act"
onClick={() => {
handleFix()
setShowPropertiesSettingModal(false)
}}
>
{getMessage('modal.cover.outline.finish')}
</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -1,24 +1,63 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange } from '@/util/input-utils'
export default function RightAngle() { export default function RightAngle({ props }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { length1, setLength1, length1Ref, length2, setLength2, length2Ref, arrow1, setArrow1, arrow2, setArrow2 } = props
return ( return (
<div className="outline-wrap"> <div className="outline-wrap">
<div className="outline-inner"> <div className="outline-inner">
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.length')}</span> <span className="mr10">{getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={1000} /> <input
type="text"
className="input-origin block"
value={length1}
ref={length1Ref}
onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setLength1(0)
setArrow1('')
}}
></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span>{getMessage('modal.cover.outline.arrow')}</span> <span>{getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className="direction up"></button> <button
<button className="direction down act"></button> className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
<button className="direction left"></button> onClick={() => {
<button className="direction right"></button> setArrow1('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow1('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow1 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow1('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow1 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow1('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>
@ -26,17 +65,53 @@ export default function RightAngle() {
<div className="outline-form"> <div className="outline-form">
<span className="mr10">{getMessage('modal.cover.outline.length')}</span> <span className="mr10">{getMessage('modal.cover.outline.length')}</span>
<div className="input-grid" style={{ width: '63px' }}> <div className="input-grid" style={{ width: '63px' }}>
<input type="text" className="input-origin block" defaultValue={1000} /> <input
type="text"
className="input-origin block"
value={length2}
ref={length2Ref}
onChange={(e) => onlyNumberInputChange(e, setLength2)}
placeholder="3000"
/>
</div> </div>
<button className="reset-btn"></button> <button
className="reset-btn"
onClick={() => {
setLength2(0)
}}
></button>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span>{getMessage('modal.cover.outline.arrow')}</span> <span>{getMessage('modal.cover.outline.arrow')}</span>
<div className="grid-direction"> <div className="grid-direction">
<button className="direction up"></button> <button
<button className="direction down act"></button> className={`direction up ${arrow2 === '↑' ? 'act' : ''}`}
<button className="direction left"></button> onClick={() => {
<button className="direction right"></button> setArrow2('↑')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
}}
></button>
<button
className={`direction down ${arrow2 === '↓' ? 'act' : ''}`}
onClick={() => {
setArrow2('↓')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
}}
></button>
<button
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
onClick={() => {
setArrow2('←')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
}}
></button>
<button
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
onClick={() => {
setArrow2('→')
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
}}
></button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -11,9 +11,102 @@ import DoublePitch from '@/components/floor-plan/modal/outerlinesetting/DoublePi
import Diagonal from '@/components/floor-plan/modal/outerlinesetting/Diagonal' import Diagonal from '@/components/floor-plan/modal/outerlinesetting/Diagonal'
export default function WallLineSetting(props) { export default function WallLineSetting(props) {
const { setShowOutlineModal } = props const { setShowOutlineModal, setShowPropertiesSettingModal } = props
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { type, setType, handleFix, handleRollback } = useOuterLineWall() const {
length1,
setLength1,
length2,
setLength2,
length1Ref,
length2Ref,
arrow1,
setArrow1,
arrow2,
setArrow2,
angle1,
setAngle1,
angle1Ref,
angle2,
setAngle2,
angle2Ref,
type,
setType,
arrow1Ref,
arrow2Ref,
outerLineDiagonalLength,
setOuterLineDiagonalLength,
outerLineDiagonalLengthRef,
handleRollback,
handleFix,
} = useOuterLineWall()
const outerLineProps = {
length1,
setLength1,
length1Ref,
arrow1,
setArrow1,
}
const rightAngleProps = {
length1,
setLength1,
length1Ref,
length2,
setLength2,
length2Ref,
arrow1,
setArrow1,
arrow2,
setArrow2,
}
const doublePitchProps = {
angle1,
setAngle1,
angle1Ref,
angle2,
setAngle2,
angle2Ref,
length1,
setLength1,
length1Ref,
length2,
setLength2,
length2Ref,
arrow1,
setArrow1,
arrow2,
setArrow2,
arrow1Ref,
arrow2Ref,
}
const angleProps = {
angle1,
setAngle1,
angle1Ref,
length1,
setLength1,
length1Ref,
}
const diagonalLineProps = {
length1,
setLength1,
length1Ref,
length2,
setLength2,
length2Ref,
outerLineDiagonalLength,
setOuterLineDiagonalLength,
outerLineDiagonalLengthRef,
arrow1,
setArrow1,
arrow2,
setArrow2,
}
return ( return (
<WithDraggable isShow={true} pos={{ x: -1390, y: 30 }}> <WithDraggable isShow={true} pos={{ x: -1390, y: 30 }}>
@ -58,15 +151,15 @@ export default function WallLineSetting(props) {
<div className="properties-setting-wrap outer"> <div className="properties-setting-wrap outer">
<div className="setting-tit">{getMessage('modal.cover.outline.setting')}</div> <div className="setting-tit">{getMessage('modal.cover.outline.setting')}</div>
{type === OUTER_LINE_TYPE.OUTER_LINE ? ( {type === OUTER_LINE_TYPE.OUTER_LINE ? (
<OuterLineWall /> <OuterLineWall props={outerLineProps} />
) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? ( ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
<RightAngle /> <RightAngle props={rightAngleProps} />
) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? ( ) : type === OUTER_LINE_TYPE.DOUBLE_PITCH ? (
<DoublePitch /> <DoublePitch props={doublePitchProps} />
) : type === OUTER_LINE_TYPE.ANGLE ? ( ) : type === OUTER_LINE_TYPE.ANGLE ? (
<Angle /> <Angle props={angleProps} />
) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? ( ) : type === OUTER_LINE_TYPE.DIAGONAL_LINE ? (
<Diagonal /> <Diagonal props={diagonalLineProps} />
) : ( ) : (
<></> <></>
)} )}
@ -75,7 +168,13 @@ export default function WallLineSetting(props) {
<button className="btn-frame modal mr5" onClick={handleRollback}> <button className="btn-frame modal mr5" onClick={handleRollback}>
{getMessage('modal.cover.outline.rollback')} {getMessage('modal.cover.outline.rollback')}
</button> </button>
<button className="btn-frame modal act" onClick={handleFix}> <button
className="btn-frame modal act"
onClick={() => {
handleFix(setShowOutlineModal)
setShowPropertiesSettingModal(true)
}}
>
{getMessage('modal.cover.outline.fix')} {getMessage('modal.cover.outline.fix')}
</button> </button>
</div> </div>

View File

@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import { distanceBetweenPoints } from '@/util/canvas-util' import { distanceBetweenPoints, getDegreeByChon } from '@/util/canvas-util'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { import {
adsorptionPointAddModeState, adsorptionPointAddModeState,
@ -16,14 +16,17 @@ import { useTempGrid } from '@/hooks/useTempGrid'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { import {
outerLineAngle1State, outerLineAngle1State,
outerLineAngle2State,
outerLineArrow1State, outerLineArrow1State,
outerLineArrow2State, outerLineArrow2State,
outerLineDiagonalState,
outerLineLength1State, outerLineLength1State,
outerLineLength2State, outerLineLength2State,
outerLinePointsState, outerLinePointsState,
outerLineTypeState, outerLineTypeState,
} from '@/store/outerLineAtom' } from '@/store/outerLineAtom'
import { calculateAngle } from '@/util/qpolygon-utils' import { calculateAngle } from '@/util/qpolygon-utils'
import { fabric } from 'fabric'
export function useOuterLineWall() { export function useOuterLineWall() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -33,6 +36,7 @@ export function useOuterLineWall() {
const { addLine, removeLine } = useLine() const { addLine, removeLine } = useLine()
const { tempGridMode } = useTempGrid() const { tempGridMode } = useTempGrid()
const { addPolygonByLines } = usePolygon() const { addPolygonByLines } = usePolygon()
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
const adsorptionPointMode = useRecoilValue(adsorptionPointModeState) const adsorptionPointMode = useRecoilValue(adsorptionPointModeState)
@ -42,28 +46,31 @@ export function useOuterLineWall() {
const length1Ref = useRef(null) const length1Ref = useRef(null)
const length2Ref = useRef(null) const length2Ref = useRef(null)
const angle1Ref = useRef(null) const angle1Ref = useRef(null)
const angle2Ref = useRef(null)
const [length1, setLength1] = useRecoilState(outerLineLength1State) const [length1, setLength1] = useRecoilState(outerLineLength1State)
const [length2, setLength2] = useRecoilState(outerLineLength2State) const [length2, setLength2] = useRecoilState(outerLineLength2State)
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State) const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State) const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
const [points, setPoints] = useRecoilState(outerLinePointsState) const [points, setPoints] = useRecoilState(outerLinePointsState)
const [type, setType] = useRecoilState(outerLineTypeState) const [type, setType] = useRecoilState(outerLineTypeState)
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State)
const [angle2, setAngle2] = useRecoilState(outerLineAngle2State)
const [outerLineDiagonalLength, setOuterLineDiagonalLength] = useRecoilState(outerLineDiagonalState)
const arrow1Ref = useRef(arrow1) const arrow1Ref = useRef(arrow1)
const arrow2Ref = useRef(arrow2) const arrow2Ref = useRef(arrow2)
const outerLineDiagonalLengthRef = useRef(null)
const isFix = useRef(false) const isFix = useRef(false)
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State) const closeModalFn = useRef(null)
useEffect(() => { useEffect(() => {
if (adsorptionPointAddMode || tempGridMode) { if (adsorptionPointAddMode || tempGridMode) {
return return
} }
removeMouseEvent('mouse:down', mouseDown)
addCanvasMouseEventListener('mouse:down', mouseDown) addCanvasMouseEventListener('mouse:down', mouseDown)
clear() clear()
return () => {
removeAllMouseEventListeners()
}
}, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode])
useEffect(() => { useEffect(() => {
@ -75,9 +82,8 @@ export function useOuterLineWall() {
}, [arrow2]) }, [arrow2])
useEffect(() => { useEffect(() => {
removeAllDocumentEventListeners()
addDocumentEventListener('keydown', document, keydown[type])
clear() clear()
addDocumentEventListener('keydown', document, keydown[type])
}, [type]) }, [type])
const clear = () => { const clear = () => {
@ -88,6 +94,9 @@ export function useOuterLineWall() {
setArrow2('') setArrow2('')
setAngle1(0) setAngle1(0)
setAngle2(0)
setOuterLineDiagonalLength(0)
} }
const mouseDown = (e) => { const mouseDown = (e) => {
@ -143,14 +152,13 @@ export function useOuterLineWall() {
canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint')) canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint'))
// point가 변경 될때마다 이벤트 리스너를 제거하고 다시 등록
removeAllDocumentEventListeners()
addDocumentEventListener('keydown', document, keydown[type])
if (points.length === 0) { if (points.length === 0) {
removeAllDocumentEventListeners()
return return
} }
addDocumentEventListener('keydown', document, keydown[type])
if (points.length === 1) { if (points.length === 1) {
const point = new fabric.Circle({ const point = new fabric.Circle({
radius: 5, radius: 5,
@ -174,6 +182,13 @@ export function useOuterLineWall() {
const lastPoint = points[points.length - 1] const lastPoint = points[points.length - 1]
const firstPoint = points[0] const firstPoint = points[0]
if (isFix.current) {
canvas?.renderAll()
closeModalFn.current(false)
removeAllMouseEventListeners()
removeAllDocumentEventListeners()
}
if (points.length < 3) { if (points.length < 3) {
return return
} }
@ -241,7 +256,7 @@ export function useOuterLineWall() {
stroke: 'black', stroke: 'black',
strokeWidth: 3, strokeWidth: 3,
idx: idx, idx: idx,
selectable: false, selectable: true,
name: 'outerLine', name: 'outerLine',
}) })
} }
@ -261,7 +276,26 @@ export function useOuterLineWall() {
} }
// 직각 완료될 경우 확인 // 직각 완료될 경우 확인
const checkRightAngle = () => { const checkRightAngle = (direction) => {
const activeElem = document.activeElement
const canDirection =
direction === '↓' || direction === '↑'
? arrow1Ref.current === '←' || arrow1Ref.current === '→'
: arrow1Ref.current === '↓' || arrow1Ref.current === '↑'
if (activeElem === length1Ref.current || activeElem === angle1Ref.current) {
setArrow1(direction)
arrow1Ref.current = direction
length2Ref.current.focus()
} else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) {
if (!canDirection) {
return
}
setArrow2(direction)
arrow2Ref.current = direction
}
const length1Num = Number(length1Ref.current.value) / 10 const length1Num = Number(length1Ref.current.value) / 10
const length2Num = Number(length2Ref.current.value) / 10 const length2Num = Number(length2Ref.current.value) / 10
@ -332,6 +366,191 @@ export function useOuterLineWall() {
} }
} }
//이구배 완료될 경우 확인 ↓, ↑, ←, →
const checkDoublePitch = (direction) => {
const activeElem = document.activeElement
const canDirection =
direction === '↓' || direction === '↑'
? arrow1Ref.current === '←' || arrow1Ref.current === '→'
: arrow1Ref.current === '↓' || arrow1Ref.current === '↑'
if (activeElem === length1Ref.current || activeElem === angle1Ref.current) {
setArrow1(direction)
arrow1Ref.current = direction
angle2Ref.current.focus()
} else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) {
if (!canDirection) {
return
}
setArrow2(direction)
arrow2Ref.current = direction
}
const angle1Value = angle1Ref.current.value
const angle2Value = angle2Ref.current.value
const length1Value = length1Ref.current.value
const length2Value = length2Ref.current.value
const arrow1Value = arrow1Ref.current
const arrow2Value = arrow2Ref.current
if (angle1Value !== 0 && length1Value !== 0 && angle2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') {
if (arrow1Value === '↓' && arrow2Value === '→') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }]
})
} else if (arrow1Value === '↓' && arrow2Value === '←') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x - length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }]
})
} else if (arrow1Value === '↑' && arrow2Value === '→') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y - length2Value / 10 }]
})
} else if (arrow1Value === '↑' && arrow2Value === '←') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x - length1Value / 10, y: prev[prev.length - 1].y - length2Value / 10 }]
})
} else if (arrow1Value === '→' && arrow2Value === '↓') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }]
})
} else if (arrow1Value === '→' && arrow2Value === '↑') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }]
})
} else if (arrow1Value === '←' && arrow2Value === '↓') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }]
})
} else if (arrow1Value === '←' && arrow2Value === '↑') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }]
})
}
angle1Ref.current.focus()
}
}
//대각선 완료될 경우 확인
const checkDiagonal = (direction) => {
const activeElem = document.activeElement
const canDirection =
direction === '↓' || direction === '↑'
? arrow1Ref.current === '←' || arrow1Ref.current === '→'
: arrow1Ref.current === '↓' || arrow1Ref.current === '↑'
if (activeElem === length1Ref.current) {
setArrow1(direction)
arrow1Ref.current = direction
} else if (activeElem === length2Ref.current || activeElem === angle2Ref.current) {
if (!canDirection) {
return
}
setArrow2(direction)
arrow2Ref.current = direction
}
const diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이
const length1Value = length1Ref.current.value
const arrow1Value = arrow1Ref.current
const arrow2Value = arrow2Ref.current
const getLength2 = () => {
return Math.floor(Math.sqrt(diagonalLength ** 2 - length1Value ** 2))
}
const length2Value = getLength2()
console.log(length2Value)
if (diagonalLength !== 0 && length1Value !== 0 && arrow1Value !== '') {
setLength2(getLength2())
length2Ref.current.focus()
}
if (length1Value !== 0 && length2Value !== 0 && arrow1Value !== '' && arrow2Value !== '') {
if (arrow1Value === '↓' && arrow2Value === '→') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }]
})
} else if (arrow1Value === '↓' && arrow2Value === '←') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y + length1Value / 10 }]
})
} else if (arrow1Value === '↑' && arrow2Value === '→') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }]
})
} else if (arrow1Value === '↑' && arrow2Value === '←') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x - length2Value / 10, y: prev[prev.length - 1].y - length1Value / 10 }]
})
} else if (arrow1Value === '→' && arrow2Value === '↓') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [...prev, { x: prev[prev.length - 1].x + length1Value / 10, y: prev[prev.length - 1].y + length2Value / 10 }]
})
} else if (arrow1Value === '→' && arrow2Value === '↑') {
setPoints((prev) => {
if (prev.length === 0) {
return []
}
return [
...prev,
{
x: prev[prev.length - 1].x + length1Value / 10,
y: prev[prev.length - 1].y - length2Value / 10,
},
]
})
}
}
}
const keydown = { const keydown = {
outerLine: (e) => { outerLine: (e) => {
if (points.length === 0) { if (points.length === 0) {
@ -411,75 +630,52 @@ export function useOuterLineWall() {
switch (key) { switch (key) {
case 'Down': // IE/Edge에서 사용되는 값 case 'Down': // IE/Edge에서 사용되는 값
case 'ArrowDown': { case 'ArrowDown': {
if (activeElem === length1Ref.current) { checkRightAngle('↓')
setArrow1('↓')
arrow1Ref.current = '↓'
length2Ref.current.focus()
} else if (activeElem === length2Ref.current) {
if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
break
}
setArrow2('↓')
arrow2Ref.current = '↓'
checkRightAngle()
}
break break
} }
case 'Up': // IE/Edge에서 사용되는 값 case 'Up': // IE/Edge에서 사용되는 값
case 'ArrowUp': case 'ArrowUp':
if (activeElem === length1Ref.current) { checkRightAngle('↑')
setArrow1('↑')
arrow1Ref.current = '↑'
length2Ref.current.focus()
} else if (activeElem === length2Ref.current) {
if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
break
}
setArrow2('↑')
arrow2Ref.current = '↑'
checkRightAngle()
}
break break
case 'Left': // IE/Edge에서 사용되는 값 case 'Left': // IE/Edge에서 사용되는 값
case 'ArrowLeft': case 'ArrowLeft':
if (activeElem === length1Ref.current) { checkRightAngle('←')
setArrow1('←')
arrow1Ref.current = '←'
length2Ref.current.focus()
} else if (activeElem === length2Ref.current) {
if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
break
}
setArrow2('←')
arrow2Ref.current = '←'
checkRightAngle()
}
break break
case 'Right': // IE/Edge에서 사용되는 값 case 'Right': // IE/Edge에서 사용되는 값
case 'ArrowRight': case 'ArrowRight':
if (activeElem === length1Ref.current) { checkRightAngle('→')
setArrow1('→')
arrow1Ref.current = '→'
length2Ref.current.focus()
} else if (activeElem === length2Ref.current) {
if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
break
}
setArrow2('→')
arrow2Ref.current = '→'
checkRightAngle()
}
break break
} }
}, },
leeGubae: (e) => { doublePitch: (e) => {
console.log('leegubae') if (points.length === 0) {
return
}
const key = e.key
switch (key) {
case 'Down': // IE/Edge에서 사용되는 값
case 'ArrowDown': {
checkDoublePitch('↓')
break
}
case 'Up': // IE/Edge에서 사용되는 값
case 'ArrowUp':
checkDoublePitch('↑')
break
case 'Left': // IE/Edge에서 사용되는 값
case 'ArrowLeft':
checkDoublePitch('←')
break
case 'Right': // IE/Edge에서 사용되는 값
case 'ArrowRight':
checkDoublePitch('→')
break
}
}, },
angle: (e) => { angle: (e) => {
if (points.length === 0) {
return
}
const key = e.key const key = e.key
switch (key) { switch (key) {
case 'Enter': { case 'Enter': {
@ -501,7 +697,30 @@ export function useOuterLineWall() {
} }
}, },
diagonalLine: (e) => { diagonalLine: (e) => {
console.log('diagonalLine') if (points.length === 0) {
return
}
const key = e.key
switch (key) {
case 'Down': // IE/Edge에서 사용되는 값
case 'ArrowDown': {
checkDiagonal('↓')
break
}
case 'Up': // IE/Edge에서 사용되는 값
case 'ArrowUp':
checkDiagonal('↑')
break
case 'Left': // IE/Edge에서 사용되는 값
case 'ArrowLeft':
checkDiagonal('←')
break
case 'Right': // IE/Edge에서 사용되는 값
case 'ArrowRight':
checkDiagonal('→')
break
}
}, },
} }
@ -513,7 +732,7 @@ export function useOuterLineWall() {
setPoints((prev) => prev.slice(0, prev.length - 1)) setPoints((prev) => prev.slice(0, prev.length - 1))
} }
const handleFix = () => { const handleFix = (fn) => {
if (points.length < 3) { if (points.length < 3) {
return return
} }
@ -541,6 +760,9 @@ export function useOuterLineWall() {
setPoints((prev) => { setPoints((prev) => {
return [...prev, { x: prev[0].x, y: prev[0].y }] return [...prev, { x: prev[0].x, y: prev[0].y }]
}) })
isFix.current = true
closeModalFn.current = fn
} }
return { return {
@ -558,6 +780,15 @@ export function useOuterLineWall() {
setArrow2, setArrow2,
arrow1Ref, arrow1Ref,
arrow2Ref, arrow2Ref,
angle1,
setAngle1,
angle1Ref,
angle2,
setAngle2,
angle2Ref,
outerLineDiagonalLength,
setOuterLineDiagonalLength,
outerLineDiagonalLengthRef,
type, type,
setType, setType,
handleFix, handleFix,

View File

@ -0,0 +1,129 @@
import { useEffect, useRef } from 'react'
import { LINE_TYPE } from '@/common/common'
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
export function usePropertiesSetting() {
const currentLine = useRef(null)
const currentIdx = useRef(-1)
const canvas = useRecoilValue(canvasState)
useEffect(() => {
selectNextLine()
}, [])
const handleSetEaves = () => {
currentLine.current.set({
stroke: '#45CD7D',
strokeWidth: 4,
attributes: {
offset: 500,
type: LINE_TYPE.WALLLINE.EAVES,
pitch: 4,
},
})
canvas.renderAll()
selectNextLine()
}
const handleSetGable = () => {
currentLine.current.set({
stroke: '#3FBAE6',
strokeWidth: 4,
attributes: {
offset: 300,
type: LINE_TYPE.WALLLINE.GABLE,
},
})
canvas.renderAll()
selectNextLine()
}
const selectNextLine = () => {
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
currentIdx.current++
if (currentIdx.current >= lines.length) {
currentIdx.current = lines.length
currentLine.current = lines[currentIdx.current - 1]
return
}
currentLine.current = lines[currentIdx.current]
currentLine.current.set({
stroke: '#EA10AC',
strokeWidth: 4,
})
canvas.renderAll()
}
const selectPrevLine = () => {
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
currentIdx.current--
if (currentIdx.current <= -1) {
currentIdx.current = -1
selectNextLine()
return
} else {
lines.forEach((line, index) => {
if (index >= currentIdx.current) {
delete line.attributes
line.set({
stroke: '#000000',
strokeWidth: 4,
})
}
currentIdx.current--
canvas.renderAll()
selectNextLine()
})
}
}
const handleRollback = () => {
selectPrevLine()
}
const handleFix = () => {
if (!confirm('외벽선 속성 설정을 완료하시겠습니까?')) {
return
}
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
lines.forEach((line) => {
line.set({
attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
stroke: '#000000',
strokeWidth: 4,
})
})
canvas.renderAll()
}
const closeModal = (fn) => {
if (!confirm('외벽선 속성 설정을 종료 하시겠습니까?')) {
return
}
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
lines.forEach((line) => {
line.set({
attributes: { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
stroke: '#000000',
strokeWidth: 4,
})
})
canvas.renderAll()
fn(false)
}
return { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal }
}

View File

@ -26,7 +26,7 @@ export function useAdsorptionPoint() {
top: pointer.y - 3, top: pointer.y - 3,
x: pointer.x, x: pointer.x,
y: pointer.y, y: pointer.y,
selectable: false, selectable: true,
name: 'adsorptionPoint', name: 'adsorptionPoint',
}) })

View File

@ -36,6 +36,7 @@ export function useCanvas(id) {
setCanvas(c) setCanvas(c)
setCanvasForEvent(c) setCanvasForEvent(c)
attachDefaultEventOnCanvas()
return () => { return () => {
// c.dispose() // c.dispose()
@ -45,7 +46,6 @@ export function useCanvas(id) {
useEffect(() => { useEffect(() => {
// canvas 사이즈가 변경되면 다시 // canvas 사이즈가 변경되면 다시
attachDefaultEventOnCanvas()
}, [canvasSize]) }, [canvasSize])
useEffect(() => { useEffect(() => {
@ -91,6 +91,13 @@ export function useCanvas(id) {
// settings for all canvas in the app // settings for all canvas in the app
fabric.Object.prototype.transparentCorners = false fabric.Object.prototype.transparentCorners = false
fabric.Object.prototype.id = uuidv4() fabric.Object.prototype.id = uuidv4()
fabric.Object.prototype.selectable = true
fabric.Object.prototype.lockMovementX = true
fabric.Object.prototype.lockMovementY = true
fabric.Object.prototype.lockRotation = true
fabric.Object.prototype.lockScalingX = true
fabric.Object.prototype.lockScalingY = true
fabric.Object.prototype.cornerColor = '#2BEBC8' fabric.Object.prototype.cornerColor = '#2BEBC8'
fabric.Object.prototype.cornerStyle = 'rect' fabric.Object.prototype.cornerStyle = 'rect'
fabric.Object.prototype.cornerStrokeColor = '#2BEBC8' fabric.Object.prototype.cornerStrokeColor = '#2BEBC8'

View File

@ -6,6 +6,7 @@ import { gridColorState } from '@/store/gridAtom'
export function useDotLineGrid() { export function useDotLineGrid() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const gridColor = useRecoilValue(gridColorState) const gridColor = useRecoilValue(gridColorState)
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState) const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격

View File

@ -1,24 +1,16 @@
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom'
adsorptionPointAddModeState,
adsorptionPointModeState,
adsorptionRangeState,
canvasState,
canvasZoomState,
currentMenuState,
} from '@/store/canvasAtom'
import { fabric } from 'fabric' import { fabric } from 'fabric'
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' import { calculateDistance, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
import { useMouse } from '@/hooks/useMouse'
import { useDotLineGrid } from '@/hooks/useDotLineGrid' import { useDotLineGrid } from '@/hooks/useDotLineGrid'
import { useTempGrid } from '@/hooks/useTempGrid' import { useTempGrid } from '@/hooks/useTempGrid'
export function useEvent() { export function useEvent() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const currentMenu = useRecoilValue(currentMenuState) const currentMenu = useRecoilValue(currentMenuState)
const keyboardEventListeners = useRef([]) const documentEventListeners = useRef([])
const mouseEventListeners = useRef([]) const mouseEventListeners = useRef([])
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
@ -30,9 +22,8 @@ export function useEvent() {
if (!canvas) { if (!canvas) {
return return
} }
removeAllMouseEventListeners()
removeAllDocumentEventListeners() removeAllDocumentEventListeners()
removeAllMouseEventListeners()
/** /**
* wheelEvent * wheelEvent
*/ */
@ -193,13 +184,14 @@ export function useEvent() {
} }
const addCanvasMouseEventListener = (eventType, handler) => { const addCanvasMouseEventListener = (eventType, handler) => {
canvas.off(eventType)
canvas.on(eventType, handler) canvas.on(eventType, handler)
mouseEventListeners.current.push({ eventType, handler }) mouseEventListeners.current.push({ eventType, handler })
} }
const removeAllMouseEventListeners = () => { const removeAllMouseEventListeners = () => {
mouseEventListeners.current.forEach(({ eventType, handler }) => { mouseEventListeners.current.forEach(({ eventType, handler }) => {
canvas.off(eventType, handler) canvas.off(eventType)
}) })
mouseEventListeners.current.length = 0 // 배열 초기화 mouseEventListeners.current.length = 0 // 배열 초기화
} }
@ -211,24 +203,36 @@ export function useEvent() {
* @param handler * @param handler
*/ */
const addDocumentEventListener = (eventType, element, handler) => { const addDocumentEventListener = (eventType, element, handler) => {
removeDocumentEvent(eventType)
element.addEventListener(eventType, handler) element.addEventListener(eventType, handler)
keyboardEventListeners.current.push({ eventType, element, handler }) documentEventListeners.current.push({ eventType, element, handler })
} }
/** /**
* document에 등록되는 event 제거 * document에 등록되는 event 제거
*/ */
const removeAllDocumentEventListeners = () => { const removeAllDocumentEventListeners = () => {
keyboardEventListeners.current.forEach(({ eventType, element, handler }) => { documentEventListeners.current.forEach(({ eventType, element, handler }) => {
element.removeEventListener(eventType, handler) element.removeEventListener(eventType, handler)
}) })
keyboardEventListeners.current.length = 0 // 배열 초기화 documentEventListeners.current.length = 0 // 배열 초기화
} }
const removeMouseEvent = (type, handler) => { const removeMouseEvent = (type) => {
mouseEventListeners.current = mouseEventListeners.current.filter((event) => { mouseEventListeners.current = mouseEventListeners.current.filter((event) => {
if (event.type === type && event.handler === handler) { if (event.eventType === type) {
canvas.off(type, handler) canvas.off(type, event.handler)
return false
}
return true
})
}
const removeDocumentEvent = (type) => {
documentEventListeners.current = documentEventListeners.current.filter((event) => {
if (event.eventType === type) {
console.log(type)
event.element.removeEventListener(type, event.handler)
return false return false
} }
return true return true

View File

@ -38,6 +38,7 @@ export const useLine = () => {
const removeLine = (line) => { const removeLine = (line) => {
removeLineText(line) removeLineText(line)
canvas?.remove(line) canvas?.remove(line)
canvas?.renderAll()
} }
const removeLineText = (line) => { const removeLineText = (line) => {