점.선 그리드 설정 기능 추가

This commit is contained in:
hyojun.choi 2024-09-26 12:57:32 +09:00
parent 5c0e3bbf4b
commit 14faacf985
10 changed files with 484 additions and 82 deletions

View File

@ -2,21 +2,225 @@ 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'
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 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') },
{ id: 2, name: '1/2' },
{ 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' },
{ 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: 'black',
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`}>
@ -29,55 +233,91 @@ export default function DotLineGrid(props) {
<div className="modal-body">
<div className="grid-check-form">
<div className="d-check-box pop">
<input type="checkbox" id="ch01" />
<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" />
<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" />
<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" defaultValue={910} />
<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" defaultValue={910} />
<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" />
<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" defaultValue={910} />
<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 title={'原寸'} options={SelectOption} />
<QSelectBox options={SelectOption} onChange={changeDimension} value={selectOption} />
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal mr5">{getMessage('modal.canvas.setting.grid.dot.line.setting.reset')}</button>
<button className="btn-frame modal act">{getMessage('modal.canvas.setting.grid.dot.line.setting.save')}</button>
<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>

View File

@ -8,8 +8,10 @@ import { useEvent } from '@/hooks/useEvent'
import {
adsorptionPointAddModeState,
adsorptionPointModeState,
adsorptionRangeState,
canvasHistoryState,
canvasState,
dotLineIntervalSelector,
verticalHorizontalModeState,
} from '@/store/canvasAtom'
import {
@ -27,22 +29,22 @@ import { distanceBetweenPoints } from '@/util/canvas-util'
import { calculateAngle } from '@/util/qpolygon-utils'
import { usePolygon } from '@/hooks/usePolygon'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
import { useMouse } from '@/hooks/useMouse'
export default function OuterLineWall(props) {
const { setShowOutlineModal } = props
const { getMessage } = useMessage()
const {
addCanvasMouseEventListener,
addDocumentEventListener,
removeAllMouseEventListeners,
removeAllDocumentEventListeners,
removeMouseEvent,
getIntersectMousePoint,
} = useEvent()
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
useEvent()
const { getIntersectMousePoint } = useMouse()
const { addLine, removeLine } = useLine()
const { addPolygonByLines } = usePolygon()
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
const adsorptionPointMode = useRecoilValue(adsorptionPointModeState)
const adsorptionRange = useRecoilValue(adsorptionRangeState)
const interval = useRecoilValue(dotLineIntervalSelector) //
const length1Ref = useRef(null)
const length2Ref = useRef(null)
@ -72,7 +74,7 @@ export default function OuterLineWall(props) {
return () => {
removeAllMouseEventListeners()
}
}, [verticalHorizontalMode, points, adsorptionPointAddMode])
}, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval])
useEffect(() => {
arrow1Ref.current = arrow1

View File

@ -113,11 +113,11 @@ export default function SecondOption() {
// HTTP POST
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
toastUp({ message: getMessage(res.returnMessage), type: 'success' })
setAdsorptionRange(option.range)
})
} catch (error) {
toastUp({ message: getMessage(res.returnMessage), type: 'error' })
}
setAdsorptionRange(option.range)
}
return (
<>

View File

@ -0,0 +1,45 @@
import { useRecoilState, useRecoilValue } from 'recoil'
import { adsorptionPointAddModeState, adsorptionPointModeState, adsorptionRangeState, canvasState } from '@/store/canvasAtom'
import { fabric } from 'fabric'
import { useMouse } from '@/hooks/useMouse'
export function useAdsorptionPoint() {
const canvas = useRecoilValue(canvasState)
const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState)
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState)
const { getIntersectMousePoint } = useMouse()
const getAdsorptionPoints = () => {
return canvas.getObjects().filter((obj) => obj.visible && obj.name === 'adsorptionPoint')
}
const adsorptionPointAddModeStateEvent = (opt) => {
//흡착점 모드일 경우
let pointer = getIntersectMousePoint(opt)
const adsorptionPoint = new fabric.Circle({
radius: 3,
fill: 'red',
left: pointer.x - 3,
top: pointer.y - 3,
x: pointer.x,
y: pointer.y,
selectable: false,
name: 'adsorptionPoint',
})
canvas.add(adsorptionPoint)
canvas.renderAll()
}
return {
adsorptionPointAddMode,
adsorptionPointMode,
adsorptionRange,
getAdsorptionPoints,
adsorptionPointAddModeStateEvent,
}
}

View File

@ -0,0 +1,51 @@
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
import { canvasState, dotLineGridSettingState, dotLineIntervalSelector } from '@/store/canvasAtom'
import { calculateDistance } from '@/util/canvas-util'
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
export function useDotLineGrid() {
const canvas = useRecoilValue(canvasState)
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격
const { adsorptionRange } = useAdsorptionPoint()
const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState)
const getLineGrids = () => {
return canvas.getObjects().filter((obj) => obj.name === 'lineGrid')
}
const getClosestLineGrid = (point) => {
const lines = getLineGrids()
if (lines.length === 0) {
return null
}
let closestLine = null
let minDistance = Infinity
lines.forEach((line) => {
const distance = calculateDistance(point, line)
if (distance < minDistance) {
minDistance = distance
closestLine = line
}
})
if (minDistance > adsorptionRange) {
return null
}
return closestLine
}
return {
dotLineGridSetting,
resetDotLineGridSetting,
getLineGrids,
getClosestLineGrid,
interval,
}
}

View File

@ -9,7 +9,10 @@ import {
currentMenuState,
} from '@/store/canvasAtom'
import { fabric } from 'fabric'
import { calculateIntersection, distanceBetweenPoints } from '@/util/canvas-util'
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
import { useMouse } from '@/hooks/useMouse'
import { useDotLineGrid } from '@/hooks/useDotLineGrid'
export function useEvent() {
const canvas = useRecoilValue(canvasState)
@ -17,10 +20,9 @@ export function useEvent() {
const keyboardEventListeners = useRef([])
const mouseEventListeners = useRef([])
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
const adsorptionPointMode = useRecoilValue(adsorptionPointModeState)
const adsorptionRange = useRecoilValue(adsorptionRangeState)
const { adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, getAdsorptionPoints, adsorptionPointAddModeStateEvent } = useAdsorptionPoint()
const { dotLineGridSetting, interval, getClosestLineGrid } = useDotLineGrid()
useEffect(() => {
if (!canvas) {
return
@ -35,7 +37,7 @@ export function useEvent() {
canvas?.on('mouse:wheel', wheelEvent)
addDefaultEvent()
}, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange])
}, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, dotLineGridSetting])
const addDefaultEvent = () => {
//default Event 추가
@ -53,26 +55,6 @@ export function useEvent() {
e.stopPropagation()
}
const adsorptionPointAddModeStateEvent = (opt) => {
//흡착점 모드일 경우
let pointer = getIntersectMousePoint(opt)
const adsorptionPoint = new fabric.Circle({
radius: 3,
fill: 'red',
left: pointer.x - 3,
top: pointer.y - 3,
x: pointer.x,
y: pointer.y,
selectable: false,
name: 'adsorptionPoint',
})
canvas.add(adsorptionPoint)
canvas.renderAll()
}
const wheelEvent = (opt) => {
const delta = opt.e.deltaY // 휠 이동 값 (양수면 축소, 음수면 확대)
let zoom = canvas.getZoom() // 현재 줌 값
@ -107,17 +89,61 @@ export function useEvent() {
let arrivalPoint = { x: pointer.x, y: pointer.y }
if (adsorptionPointMode) {
// pointer와 adsorptionPoints의 거리를 계산하여 가장 가까운 점을 찾는다.
let minDistance = adsorptionRange
let adsorptionPoint = null
adsorptionPoints.forEach((point) => {
const distance = distanceBetweenPoints(pointer, point)
if (distance < minDistance) {
minDistance = distance
adsorptionPoint = point
if (dotLineGridSetting.LINE) {
const closestLine = getClosestLineGrid(pointer)
if (closestLine) {
const distance = calculateDistance(pointer, closestLine)
if (distance < adsorptionRange) {
arrivalPoint = closestLine.direction === 'vertical' ? { x: closestLine.x1, y: pointer.y } : { x: pointer.x, y: closestLine.y1 }
}
}
})
if (adsorptionPoint) {
}
if (dotLineGridSetting.DOT) {
const horizontalInterval = interval.horizontalInterval
const verticalInterval = interval.verticalInterval
const x = pointer.x - horizontalInterval * Math.floor(pointer.x / horizontalInterval)
const y = pointer.y - verticalInterval * Math.floor(pointer.y / verticalInterval)
const xRate = (x / horizontalInterval) * 100
const yRate = (y / verticalInterval) * 100
let tempPoint
if (xRate <= adsorptionRange && yRate <= adsorptionRange) {
tempPoint = {
x: Math.round(pointer.x / horizontalInterval) * horizontalInterval + horizontalInterval / 2,
y: Math.round(pointer.y / verticalInterval) * verticalInterval + horizontalInterval / 2,
}
} else if (xRate <= adsorptionRange && yRate >= adsorptionRange) {
tempPoint = {
x: Math.round(pointer.x / horizontalInterval) * horizontalInterval + horizontalInterval / 2,
y: Math.round(pointer.y / verticalInterval) * verticalInterval - horizontalInterval / 2,
}
} else if (xRate >= adsorptionRange && yRate <= adsorptionRange) {
tempPoint = {
x: Math.round(pointer.x / horizontalInterval) * horizontalInterval - horizontalInterval / 2,
y: Math.round(pointer.y / verticalInterval) * verticalInterval + horizontalInterval / 2,
}
} else if (xRate >= adsorptionRange && yRate >= adsorptionRange) {
tempPoint = {
x: Math.round(pointer.x / horizontalInterval) * horizontalInterval - horizontalInterval / 2,
y: Math.round(pointer.y / verticalInterval) * verticalInterval - horizontalInterval / 2,
}
}
if (distanceBetweenPoints(pointer, tempPoint) <= adsorptionRange) {
arrivalPoint = tempPoint
}
}
// pointer와 adsorptionPoints의 거리를 계산하여 가장 가까운 점을 찾는다.
let adsorptionPoint = findClosestPoint(pointer, adsorptionPoints)
if (adsorptionPoint && distanceBetweenPoints(pointer, adsorptionPoint) <= adsorptionRange) {
arrivalPoint = { ...adsorptionPoint }
}
}
@ -203,28 +229,11 @@ export function useEvent() {
})
}
const getAdsorptionPoints = () => {
return canvas.getObjects().filter((obj) => obj.visible && obj.name === 'adsorptionPoint')
}
//가로선, 세로선의 교차점을 return
const getIntersectMousePoint = (e) => {
let pointer = canvas.getPointer(e.e)
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
if (mouseLines.length < 2) {
return pointer
}
return calculateIntersection(mouseLines[0], mouseLines[1]) ?? pointer
}
return {
addDocumentEventListener,
addCanvasMouseEventListener,
removeAllMouseEventListeners,
removeAllDocumentEventListeners,
removeMouseEvent,
getIntersectMousePoint,
}
}

23
src/hooks/useMouse.js Normal file
View File

@ -0,0 +1,23 @@
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { calculateIntersection } from '@/util/canvas-util'
export function useMouse() {
const canvas = useRecoilValue(canvasState)
//가로선, 세로선의 교차점을 return
const getIntersectMousePoint = (e) => {
let pointer = canvas.getPointer(e.e)
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
if (mouseLines.length < 2) {
return pointer
}
return calculateIntersection(mouseLines[0], mouseLines[1]) || pointer
}
return {
getIntersectMousePoint,
}
}

View File

@ -205,7 +205,7 @@ export const verticalHorizontalModeState = atom({
// 흡착점 모드
export const adsorptionPointModeState = atom({
key: 'adsorptionPointModeState',
default: false,
default: true,
})
// 흡착점 추가모드
export const adsorptionPointAddModeState = atom({
@ -218,3 +218,35 @@ export const adsorptionRangeState = atom({
key: 'adsorptionRangeState',
default: 50,
})
// 점,선 그리드 설정
export const dotLineGridSettingState = atom({
key: 'gridSettingState',
default: {
INTERVAL: {
type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격
ratioInterval: 910,
verticalInterval: 910,
horizontalInterval: 910,
dimension: 1, // 치수
},
DOT: false,
LINE: false,
},
})
export const dotLineIntervalSelector = selector({
key: 'dotLineIntervalSelector',
get: ({ get }) => {
const gridSetting = get(dotLineGridSettingState)
return gridSetting.INTERVAL.type === 1
? {
horizontalInterval: Math.round(gridSetting.INTERVAL.horizontalInterval / 10),
verticalInterval: Math.round(gridSetting.INTERVAL.verticalInterval / 10),
}
: {
horizontalInterval: Math.round((gridSetting.INTERVAL.ratioInterval * gridSetting.INTERVAL.dimension) / 10),
verticalInterval: Math.round((gridSetting.INTERVAL.ratioInterval * gridSetting.INTERVAL.dimension) / 10),
}
},
})

View File

@ -50,9 +50,9 @@ export const settingModalSecondOptionsState = atom({
],
option4: [
{ id: 1, column: 'adsorpRangeSmall', name: 'modal.canvas.setting.font.plan.absorption.small', selected: true, range: 10 },
{ id: 2, column: 'adsorpRangeSmallSemi', name: 'modal.canvas.setting.font.plan.absorption.small.semi', selected: false, range: 30 },
{ id: 3, column: 'adsorpRangeMedium', name: 'modal.canvas.setting.font.plan.absorption.medium', selected: false, range: 50 },
{ id: 4, column: 'adsorpRangeLarge', name: 'modal.canvas.setting.font.plan.absorption.large', selected: false, range: 80 },
{ id: 2, column: 'adsorpRangeSmallSemi', name: 'modal.canvas.setting.font.plan.absorption.small.semi', selected: false, range: 20 },
{ id: 3, column: 'adsorpRangeMedium', name: 'modal.canvas.setting.font.plan.absorption.medium', selected: false, range: 30 },
{ id: 4, column: 'adsorpRangeLarge', name: 'modal.canvas.setting.font.plan.absorption.large', selected: false, range: 40 },
],
},
dangerouslyAllowMutability: true,

View File

@ -2,7 +2,7 @@
export const onlyNumberInputChange = (e, callback) => {
let value = e.target.value.replace(/^0+/, '')
value = value.replace(/[^-0-9]/g, '')
callback(value)
callback(value, e)
}
//소수점 둘째자리 숫자만 입력가능
@ -12,9 +12,9 @@ export const onlyNumberWithDotInputChange = (e, callback) => {
const pattern = /^-?(\d{1,4}([.]\d{0,2})?)?$/
if (!pattern.test(val)) {
// prev에서 마지막 자리 제거
callback(val.slice(0, val.length - 1))
callback(val.slice(0, val.length - 1), e)
return
}
callback(val)
callback(val, e)
}