Merge remote-tracking branch 'origin/qcast-pub' into dev
This commit is contained in:
commit
be2de96fbb
@ -3,13 +3,23 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { currentObjectState } from '@/store/canvasAtom'
|
||||||
|
import { useGrid } from '@/hooks/common/useGrid'
|
||||||
|
|
||||||
export default function GridCopy(props) {
|
export default function GridCopy(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const [length, setLength] = useState('0')
|
||||||
|
const [arrow, setArrow] = useState(null)
|
||||||
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
|
const { copy } = useGrid()
|
||||||
|
const handleApply = () => {
|
||||||
|
// copy(currentObject, )
|
||||||
|
copy(currentObject, ['↑', '←'].includes(arrow) ? Number(length) * -1 : Number(length))
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm mount`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
@ -26,20 +36,46 @@ export default function GridCopy(props) {
|
|||||||
<div className="grid-input-form">
|
<div className="grid-input-form">
|
||||||
<span className="mr10">{getMessage('modal.grid.copy.length')}</span>
|
<span className="mr10">{getMessage('modal.grid.copy.length')}</span>
|
||||||
<div className="input-grid mr5">
|
<div className="input-grid mr5">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input type="text" className="input-origin" value={length} onChange={(e) => setLength(e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-direction">
|
<div className="grid-direction">
|
||||||
<button className="direction up"></button>
|
<button
|
||||||
<button className="direction down act"></button>
|
className={`direction up ${arrow === '↑' ? 'act' : ''} ${currentObject?.direction === 'vertical' ? 'no-click' : ''}`}
|
||||||
<button className="direction left"></button>
|
onClick={() => {
|
||||||
<button className="direction right"></button>
|
if (currentObject?.direction === 'vertical') return
|
||||||
|
setArrow('↑')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction down ${arrow === '↓' ? 'act' : ''} ${currentObject?.direction === 'vertical' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (currentObject?.direction === 'vertical') return
|
||||||
|
setArrow('↓')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction left ${arrow === '←' ? 'act' : ''} ${currentObject?.direction === 'horizontal' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (currentObject?.direction === 'horizontal') return
|
||||||
|
setArrow('←')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction right ${arrow === '→' ? 'act' : ''} ${currentObject?.direction === 'horizontal' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (currentObject?.direction === 'horizontal') return
|
||||||
|
setArrow('→')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">{getMessage('modal.grid.copy.save')}</button>
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.grid.copy.save')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,21 +1,83 @@
|
|||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||||
|
import { useCanvas } from '@/hooks/useCanvas'
|
||||||
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useGrid } from '@/hooks/common/useGrid'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
import { set } from 'react-hook-form'
|
||||||
|
|
||||||
export default function GridMove(props) {
|
export default function GridMove(props) {
|
||||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||||
const { id, pos = contextPopupPosition } = props
|
const { id, pos = contextPopupPosition } = props
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const { swalFire } = useSwal()
|
||||||
|
const { move } = useGrid()
|
||||||
|
const [currentObject, setCurrentObject] = useRecoilState(currentObjectState)
|
||||||
|
const [isAll, setIsAll] = useState(false)
|
||||||
|
const [verticalSize, setVerticalSize] = useState('0')
|
||||||
|
const [horizonSize, setHorizonSize] = useState('0')
|
||||||
|
const [arrow1, setArrow1] = useState(null)
|
||||||
|
const [arrow2, setArrow2] = useState(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentObject?.direction === 'vertical') {
|
||||||
|
setArrow1(null)
|
||||||
|
setVerticalSize('0')
|
||||||
|
} else {
|
||||||
|
setArrow2(null)
|
||||||
|
setHorizonSize('0')
|
||||||
|
}
|
||||||
|
}, [currentObject])
|
||||||
|
|
||||||
|
const handleApply = () => {
|
||||||
|
if (currentObject?.direction === 'vertical') {
|
||||||
|
if (!horizonSize || !arrow2) {
|
||||||
|
swalFire({ title: '길이와 방향을 입력하세요.', type: 'alert' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!verticalSize || !arrow1) {
|
||||||
|
swalFire({ title: '길이와 방향을 입력하세요.', type: 'alert' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAll) {
|
||||||
|
canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => ['lineGrid', 'tempGrid', 'dotGrid'].includes(obj.name))
|
||||||
|
.forEach((grid) => {
|
||||||
|
move(
|
||||||
|
grid,
|
||||||
|
arrow2 === '←' ? Number(horizonSize) * -1 : Number(horizonSize),
|
||||||
|
arrow1 === '↑' ? Number(verticalSize) * -1 : Number(verticalSize),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
move(
|
||||||
|
currentObject,
|
||||||
|
arrow2 === '←' ? Number(horizonSize) * -1 : Number(horizonSize),
|
||||||
|
arrow1 === '↑' ? Number(verticalSize) * -1 : Number(verticalSize),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
canvas.renderAll()
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
closePopup(id)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap xm mount`}>
|
<div className={`modal-pop-wrap xm mount`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.grid.move')} </h1>
|
<h1 className="title">{getMessage('modal.grid.move')} </h1>
|
||||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
<button className="modal-close" onClick={handleClose}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -23,7 +85,7 @@ export default function GridMove(props) {
|
|||||||
<div className="grid-option-tit">{getMessage('modal.grid.move.info')}</div>
|
<div className="grid-option-tit">{getMessage('modal.grid.move.info')}</div>
|
||||||
<div className="grid-option-wrap">
|
<div className="grid-option-wrap">
|
||||||
<div className="d-check-box pop mb10">
|
<div className="d-check-box pop mb10">
|
||||||
<input type="checkbox" id="ch99" />
|
<input type="checkbox" id="ch99" checked={isAll} onChange={() => setIsAll(!isAll)} />
|
||||||
<label htmlFor="ch99">{getMessage('modal.grid.move.all')}</label>
|
<label htmlFor="ch99">{getMessage('modal.grid.move.all')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-option-box">
|
<div className="grid-option-box">
|
||||||
@ -31,29 +93,67 @@ export default function GridMove(props) {
|
|||||||
<p className="mb5">{getMessage('modal.grid.move.length')}</p>
|
<p className="mb5">{getMessage('modal.grid.move.length')}</p>
|
||||||
<div className="input-move-wrap mb5">
|
<div className="input-move-wrap mb5">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin"
|
||||||
|
value={verticalSize}
|
||||||
|
onChange={(e) => setVerticalSize(e.target.value)}
|
||||||
|
readOnly={!isAll && currentObject?.direction === 'vertical'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
<div className="direction-move-wrap">
|
<div className="direction-move-wrap">
|
||||||
<button className="direction up"></button>
|
<button
|
||||||
<button className="direction down act"></button>
|
className={`direction up ${arrow1 === '↑' ? 'act' : ''} ${!isAll && currentObject?.direction === 'vertical' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↑')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction down ${arrow1 === '↓' ? 'act' : ''} ${!isAll && currentObject?.direction === 'vertical' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow1('↓')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-move-wrap">
|
<div className="input-move-wrap">
|
||||||
<div className="input-move">
|
<div className="input-move">
|
||||||
<input type="text" className="input-origin" defaultValue={910} />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin"
|
||||||
|
value={horizonSize}
|
||||||
|
onChange={(e) => setHorizonSize(e.target.value)}
|
||||||
|
readOnly={!isAll && currentObject?.direction === 'horizontal'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
<div className="direction-move-wrap">
|
<div className="direction-move-wrap">
|
||||||
<button className="direction left"></button>
|
<button
|
||||||
<button className="direction right"></button>
|
className={`direction left ${arrow2 === '←' ? 'act' : ''} ${!isAll && currentObject?.direction === 'horizontal' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow2('←')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`direction right ${arrow2 === '→' ? 'act' : ''} ${!isAll && currentObject?.direction === 'horizontal' ? 'no-click' : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
setArrow2('→')
|
||||||
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act">{getMessage('modal.grid.move.save')}</button>
|
<button className="btn-frame modal act" onClick={handleApply}>
|
||||||
|
{getMessage('modal.grid.move.save')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { canvasState, dotLineGridSettingState } from '@/store/canvasAtom'
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||||
|
const GRID_PADDING = 5
|
||||||
export function useGrid() {
|
export function useGrid() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
@ -108,6 +108,7 @@ export function useGrid() {
|
|||||||
name: 'lineGrid',
|
name: 'lineGrid',
|
||||||
strokeDashArray: [5, 2],
|
strokeDashArray: [5, 2],
|
||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
|
padding: GRID_PADDING,
|
||||||
direction: 'horizontal',
|
direction: 'horizontal',
|
||||||
visible: isGridDisplay,
|
visible: isGridDisplay,
|
||||||
},
|
},
|
||||||
@ -130,6 +131,7 @@ export function useGrid() {
|
|||||||
name: 'lineGrid',
|
name: 'lineGrid',
|
||||||
strokeDashArray: [5, 2],
|
strokeDashArray: [5, 2],
|
||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
|
padding: GRID_PADDING,
|
||||||
direction: 'vertical',
|
direction: 'vertical',
|
||||||
visible: isGridDisplay,
|
visible: isGridDisplay,
|
||||||
},
|
},
|
||||||
@ -141,5 +143,46 @@ export function useGrid() {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}, [dotLineGridSetting])
|
}, [dotLineGridSetting])
|
||||||
|
|
||||||
return {}
|
const move = (object, x, y) => {
|
||||||
|
object.set({
|
||||||
|
...object,
|
||||||
|
x1: object.direction === 'vertical' ? object.x1 + x : 0,
|
||||||
|
x2: object.direction === 'vertical' ? object.x1 + x : canvas.width,
|
||||||
|
y1: object.direction === 'vertical' ? 0 : object.y1 + y,
|
||||||
|
y2: object.direction === 'vertical' ? canvas.height : object.y1 + y,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const copy = (object, length) => {
|
||||||
|
const lineStartX = object.direction === 'vertical' ? object.x1 + length : 0
|
||||||
|
const lineEndX = object.direction === 'vertical' ? object.x2 + length : canvas.width
|
||||||
|
const lineStartY = object.direction === 'vertical' ? 0 : object.y1 + length
|
||||||
|
const lineEndY = object.direction === 'vertical' ? canvas.width : object.y1 + length
|
||||||
|
|
||||||
|
const line = new fabric.Line([lineStartX, lineStartY, lineEndX, lineEndY], {
|
||||||
|
stroke: gridColor,
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: true,
|
||||||
|
lockMovementX: true,
|
||||||
|
lockMovementY: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
|
strokeDashArray: [5, 2],
|
||||||
|
opacity: 0.3,
|
||||||
|
padding: GRID_PADDING,
|
||||||
|
direction: object.direction,
|
||||||
|
visible: isGridDisplay,
|
||||||
|
name: object.name,
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.add(line)
|
||||||
|
canvas.setActiveObject(line)
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
move,
|
||||||
|
copy,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -521,11 +521,23 @@ export function useContextMenu() {
|
|||||||
{
|
{
|
||||||
id: 'remove',
|
id: 'remove',
|
||||||
name: getMessage('contextmenu.remove'),
|
name: getMessage('contextmenu.remove'),
|
||||||
|
fn: () => {
|
||||||
|
canvas.remove(currentObject)
|
||||||
|
canvas.discardActiveObject()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'removeAll',
|
id: 'removeAll',
|
||||||
name: getMessage('contextmenu.remove.all'),
|
name: getMessage('contextmenu.remove.all'),
|
||||||
fn: () => {},
|
fn: () => {
|
||||||
|
canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => ['tempGrid', 'lineGrid', 'dotGrid'].includes(obj.name))
|
||||||
|
.forEach((grid) => {
|
||||||
|
canvas.remove(grid)
|
||||||
|
})
|
||||||
|
canvas.discardActiveObject()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
])
|
])
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { useRecoilState, useRecoilValue } from 'recoil'
|
|||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||||
|
|
||||||
|
const GRID_PADDING = 5
|
||||||
export function useTempGrid() {
|
export function useTempGrid() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const gridColor = useRecoilValue(gridColorState)
|
const gridColor = useRecoilValue(gridColorState)
|
||||||
@ -23,6 +24,7 @@ export function useTempGrid() {
|
|||||||
lockScalingY: true,
|
lockScalingY: true,
|
||||||
strokeDashArray: [5, 2],
|
strokeDashArray: [5, 2],
|
||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
|
padding: GRID_PADDING,
|
||||||
direction: 'vertical',
|
direction: 'vertical',
|
||||||
visible: isGridDisplay,
|
visible: isGridDisplay,
|
||||||
name: 'tempGrid',
|
name: 'tempGrid',
|
||||||
@ -50,6 +52,7 @@ export function useTempGrid() {
|
|||||||
lockScalingY: true,
|
lockScalingY: true,
|
||||||
strokeDashArray: [5, 2],
|
strokeDashArray: [5, 2],
|
||||||
opacity: 0.3,
|
opacity: 0.3,
|
||||||
|
padding: GRID_PADDING,
|
||||||
name: 'tempGrid',
|
name: 'tempGrid',
|
||||||
visible: isGridDisplay,
|
visible: isGridDisplay,
|
||||||
direction: 'horizontal',
|
direction: 'horizontal',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user