사각형 생성 모드 추가, redo, undo 추가

This commit is contained in:
hyojun.choi 2024-06-24 16:58:06 +09:00
parent 1572c9ca11
commit c3162e80b4
3 changed files with 72 additions and 5 deletions

View File

@ -5,6 +5,7 @@ export const MODE = {
EDIT: 'edit', EDIT: 'edit',
TEMPLATE: 'template', TEMPLATE: 'template',
TEXTBOX: 'textbox', TEXTBOX: 'textbox',
DRAW_RECT: 'drawRect',
} }
export function useMode() { export function useMode() {
@ -25,6 +26,9 @@ export function useMode() {
case 'textbox': case 'textbox':
textboxMode(canvas) textboxMode(canvas)
break break
case 'drawRect':
drawRectMode(canvas)
break
} }
} }
@ -194,5 +198,46 @@ export function useMode() {
}) })
} }
const drawRectMode = (canvas) => {
let rect, isDown, origX, origY
canvas.on('mouse:down', function (o) {
isDown = true
const pointer = canvas.getPointer(o.e)
origX = pointer.x
origY = pointer.y
rect = new fabric.Rect({
left: origX,
top: origY,
originX: 'left',
originY: 'top',
width: pointer.x - origX,
height: pointer.y - origY,
angle: 0,
fill: 'rgba(255,0,0,0.5)',
transparentCorners: false,
})
canvas.add(rect)
})
canvas.on('mouse:move', function (o) {
if (!isDown) return
const pointer = canvas.getPointer(o.e)
if (origX > pointer.x) {
rect.set({ left: Math.abs(pointer.x) })
}
if (origY > pointer.y) {
rect.set({ top: Math.abs(pointer.y) })
}
rect.set({ width: Math.abs(origX - pointer.x) })
rect.set({ height: Math.abs(origY - pointer.y) })
canvas.renderAll()
})
canvas.on('mouse:up', function (o) {
isDown = false
})
}
return { mode, changeMode } return { mode, changeMode }
} }

View File

@ -3,7 +3,7 @@ import { useEffect } from 'react'
import { MODE, useMode } from '@/app/mode' import { MODE, useMode } from '@/app/mode'
export default function Roof2() { export default function Roof2() {
const { canvas } = useCanvas('canvas') const { canvas, handleRedo, handleUndo } = useCanvas('canvas')
const { mode, changeMode } = useMode() const { mode, changeMode } = useMode()
@ -41,6 +41,24 @@ export default function Roof2() {
> >
텍스트박스 모드 텍스트박스 모드
</button> </button>
<button
className={`w-30 mx-2 p-2 rounded ${mode === MODE.DRAW_RECT ? 'bg-blue-500' : 'bg-gray-500'} text-white`}
onClick={() => changeMode(canvas, MODE.DRAW_RECT)}
>
사각형 생성 모드
</button>
<button
className="w-30 mx-2 p-2 rounded bg-gray-500 text-white"
onClick={handleUndo}
>
Undo
</button>
<button
className="w-30 mx-2 p-2 rounded bg-gray-500 text-white"
onClick={handleRedo}
>
Redo
</button>
</div> </div>
<div <div

View File

@ -48,6 +48,9 @@ export function useCanvas(id) {
useEffect(() => { useEffect(() => {
if (canvas) { if (canvas) {
initialize() initialize()
canvas?.on('object:added', onChange)
canvas?.on('object:modified', onChange)
canvas?.on('object:removed', onChange)
canvas?.on('mouse:move', drawMouseLines) canvas?.on('mouse:move', drawMouseLines)
canvas?.on('mouse:out', removeMouseLines) canvas?.on('mouse:out', removeMouseLines)
} }
@ -210,15 +213,16 @@ export function useCanvas(id) {
*/ */
const handleUndo = () => { const handleUndo = () => {
if (canvas) { if (canvas) {
if (canvas._objects.length > 0) { if (canvas?._objects.length > 0) {
const poppedObject = canvas._objects.pop() const poppedObject = canvas?._objects.pop()
setHistory((prev) => { setHistory((prev) => {
if (prev === undefined) { if (prev === undefined) {
return poppedObject ? [poppedObject] : [] return poppedObject ? [poppedObject] : []
} }
return poppedObject ? [...prev, poppedObject] : prev return poppedObject ? [...prev, poppedObject] : prev
}) })
canvas.renderAll() canvas?.renderAll()
} }
} }
} }
@ -227,7 +231,7 @@ export function useCanvas(id) {
if (canvas && history) { if (canvas && history) {
if (history.length > 0) { if (history.length > 0) {
setIsLocked(true) setIsLocked(true)
canvas.add(history[history.length - 1]) canvas?.add(history[history.length - 1])
const newHistory = history.slice(0, -1) const newHistory = history.slice(0, -1)
setHistory(newHistory) setHistory(newHistory)
} }