325 lines
11 KiB
JavaScript

import WithDraggable from '@/components/common/draggable/WithDraggable'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { canvasState, dotLineGridSettingState, dotLineIntervalSelector } from '@/store/canvasAtom'
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
import { onlyNumberInputChange } from '@/util/input-utils'
import { fabric } from 'fabric'
import { gridColorState } from '@/store/gridAtom'
const TYPE = {
DOT: 'DOT',
LINE: 'LINE',
}
export default function DotLineGrid(props) {
// const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state
const [close, setClose] = useState(false)
const { setShowDotLineGridModal } = props
const gridColor = useRecoilValue(gridColorState)
const canvas = useRecoilValue(canvasState)
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState)
const interval = useRecoilValue(dotLineIntervalSelector)
const { getMessage } = useMessage()
const SelectOption = [
{ id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 },
{ id: 2, name: '1/2', value: 1 / 2 },
{ id: 3, name: '1/4', value: 1 / 4 },
{ id: 4, name: '1/10', value: 1 / 10 },
]
const [selectOption, setSelectOption] = useState(SelectOption[0])
const HandleClickClose = () => {
// setClose(true)
// setTimeout(() => {
// setModalOption({ ...modalOption, gridoption: false })
// setClose(false)
// }, 180)
}
const handleCheckBoxChange = (e) => {
const { value, checked } = e.target
setDotLineGridSettingState((prev) => {
return {
...prev,
[value]: checked,
}
})
}
const handleSave = () => {
// 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거
canvas
?.getObjects()
.filter((obj) => obj.name === 'lineGrid')
.forEach((obj) => canvas?.remove(obj))
canvas
?.getObjects()
.filter((obj) => obj.name === 'dotGrid')
.forEach((obj) => canvas?.remove(obj))
const horizontalInterval = interval.horizontalInterval
const verticalInterval = interval.verticalInterval
if (dotLineGridSetting.DOT) {
const circle = new fabric.Circle({
radius: 2,
fill: 'red',
strokeWidth: 0.7,
originX: 'center',
originY: 'center',
selectable: false,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
})
const patternSourceCanvas = new fabric.StaticCanvas(null, {
width: horizontalInterval,
height: verticalInterval,
})
patternSourceCanvas.add(circle)
circle.set({
left: patternSourceCanvas.width / 2,
top: patternSourceCanvas.height / 2,
})
patternSourceCanvas.renderAll()
const pattern = new fabric.Pattern({
source: patternSourceCanvas.getElement(),
repeat: 'repeat',
})
const backgroundPolygon = new fabric.Polygon(
[
{ x: 0, y: 0 },
{ x: canvas.width, y: 0 },
{ x: canvas.width, y: canvas.height },
{ x: 0, y: canvas.height },
],
{
fill: pattern,
selectable: false,
name: 'dotGrid',
},
)
canvas.add(backgroundPolygon)
backgroundPolygon.sendToBack()
canvas.renderAll()
}
if (dotLineGridSetting.LINE) {
for (let i = 0; i < canvas.height / verticalInterval + 1; i++) {
const horizontalLine = new fabric.Line(
[0, i * verticalInterval - verticalInterval / 2, canvas.width, i * verticalInterval - verticalInterval / 2],
{
stroke: gridColor,
strokeWidth: 1,
selectable: true,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: 'lineGrid',
strokeDashArray: [5, 2],
opacity: 0.3,
direction: 'horizontal',
},
)
canvas.add(horizontalLine)
}
for (let i = 0; i < canvas.width / horizontalInterval + 1; i++) {
const verticalLine = new fabric.Line(
[i * horizontalInterval - horizontalInterval / 2, 0, i * horizontalInterval - horizontalInterval / 2, canvas.height],
{
stroke: 'black',
strokeWidth: 1,
selectable: true,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: 'lineGrid',
strokeDashArray: [5, 2],
opacity: 0.3,
direction: 'vertical',
},
)
canvas.add(verticalLine)
}
}
canvas.renderAll()
}
const handleRadioChange = (e) => {
const { value, name, checked, selected } = e.target
setDotLineGridSettingState((prev) => {
return {
...prev,
INTERVAL: {
...prev.INTERVAL,
type: Number(value),
},
}
})
}
const changeInput = (value, e) => {
const { name } = e.target
setDotLineGridSettingState((prev) => {
return {
...prev,
INTERVAL: {
...prev.INTERVAL,
[name]: value,
},
}
})
}
const changeDimension = (result) => {
const { value } = result
setDotLineGridSettingState((prev) => {
return {
...prev,
INTERVAL: {
...prev.INTERVAL,
dimension: value,
},
}
})
}
// 초기화
const reset = () => {
canvas
?.getObjects()
.filter((obj) => obj.name === 'lineGrid')
.forEach((obj) => canvas?.remove(obj))
canvas
?.getObjects()
.filter((obj) => obj.name === 'dotGrid')
.forEach((obj) => canvas?.remove(obj))
resetDotLineGridSetting()
setSelectOption(SelectOption[0])
}
return (
<WithDraggable isShow={true} pos={{ x: -150, y: 300 }}>
<div className={`modal-pop-wrap ssm mount`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.canvas.setting.grid.dot.line.setting')}</h1>
<button className="modal-close" onClick={() => setShowDotLineGridModal(false)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="grid-check-form">
<div className="d-check-box pop">
<input type="checkbox" id="ch01" value={TYPE.DOT} onChange={handleCheckBoxChange} checked={dotLineGridSetting.DOT} />
<label htmlFor="ch01">{getMessage('modal.canvas.setting.grid.dot.line.setting.dot.display')}</label>
</div>
<div className="d-check-box pop">
<input type="checkbox" id="ch02" value={TYPE.LINE} onChange={handleCheckBoxChange} checked={dotLineGridSetting.LINE} />
<label htmlFor="ch02">{getMessage('modal.canvas.setting.grid.dot.line.setting.line.display')}</label>
</div>
</div>
<div className="grid-option-wrap">
<div className="grid-option-box">
<div className="d-check-radio pop no-text">
<input
type="radio"
name="radio01"
id="ra01"
value={1}
onChange={handleRadioChange}
checked={dotLineGridSetting.INTERVAL.type === 1}
/>
<label htmlFor="ra01"></label>
</div>
<div className="grid-input-form">
<span className="mr10">{getMessage('modal.canvas.setting.grid.dot.line.setting.horizon')}</span>
<div className="input-grid mr5">
<input
type="text"
className="input-origin"
name={`horizontalInterval`}
value={dotLineGridSetting.INTERVAL.horizontalInterval}
onChange={(e) => onlyNumberInputChange(e, changeInput)}
/>
</div>
<span>mm</span>
</div>
<div className="grid-input-form">
<span className="mr10">{getMessage('modal.canvas.setting.grid.dot.line.setting.vertical')}</span>
<div className="input-grid mr5">
<input
type="text"
className="input-origin"
name={`verticalInterval`}
value={dotLineGridSetting.INTERVAL.verticalInterval}
onChange={(e) => onlyNumberInputChange(e, changeInput)}
/>
</div>
<span>mm</span>
</div>
</div>
<div className="grid-option-box">
<div className="d-check-radio pop no-text">
<input
type="radio"
name="radio01"
id="ra02"
value={2}
onChange={handleRadioChange}
checked={dotLineGridSetting.INTERVAL.type === 2}
/>
<label htmlFor="ra02"></label>
</div>
<div className="grid-input-form">
<span className="mr10">{getMessage('modal.canvas.setting.grid.dot.line.setting.ratio')}</span>
<div className="input-grid mr5">
<input
type="text"
className="input-origin"
name={`ratioInterval`}
value={dotLineGridSetting.INTERVAL.ratioInterval}
onChange={(e) => onlyNumberInputChange(e, changeInput)}
/>
</div>
<span>mm</span>
</div>
<div className="grid-select">
<QSelectBox options={SelectOption} onChange={changeDimension} value={selectOption} />
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal mr5" onClick={reset}>
{getMessage('modal.canvas.setting.grid.dot.line.setting.reset')}
</button>
<button className="btn-frame modal act" onClick={handleSave}>
{getMessage('modal.canvas.setting.grid.dot.line.setting.save')}
</button>
</div>
</div>
</div>
</WithDraggable>
)
}