From 89f4a2a94cbb125a7f3eb3ded122b3b5a999c8e4 Mon Sep 17 00:00:00 2001 From: jhynsoo Date: Thu, 12 Sep 2024 22:30:31 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EC=9B=8C=ED=81=AC=EC=8A=A4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20?= =?UTF-8?q?=EC=BA=94=EB=B2=84=EC=8A=A4=20=EC=B6=94=EA=B0=80=20-=20S11P21S0?= =?UTF-8?q?02-104?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ImageCanvas/index.tsx | 38 +--------- .../src/components/WorkspaceLayout/index.tsx | 69 ++++++++++++------- .../src/components/WorkspaceSidebar/index.tsx | 7 +- frontend/src/router/index.tsx | 3 +- frontend/src/stores/useCanvasStore.ts | 6 ++ 5 files changed, 60 insertions(+), 63 deletions(-) diff --git a/frontend/src/components/ImageCanvas/index.tsx b/frontend/src/components/ImageCanvas/index.tsx index e1dc476..bd5f80e 100644 --- a/frontend/src/components/ImageCanvas/index.tsx +++ b/frontend/src/components/ImageCanvas/index.tsx @@ -3,42 +3,15 @@ import Konva from 'konva'; import { useEffect, useRef, useState } from 'react'; import { Circle, Image, Layer, Line, Rect, Stage } from 'react-konva'; import useImage from 'use-image'; -import { Label } from '@/types'; import LabelRect from './LabelRect'; import { Vector2d } from 'konva/lib/types'; import LabelPolygon from './LabelPolygon'; import CanvasControlBar from '../CanvasControlBar'; -const mockLabels: Label[] = Array.from({ length: 10 }, (_, i) => { - const startX = Math.random() * 1200 + 300; - const startY = Math.random() * 2000 + 300; - const color = Math.floor(Math.random() * 65535) - .toString(16) - .padStart(4, '0'); - - return { - id: i, - name: `label-${i}`, - type: i % 2 === 0 ? 'polygon' : 'rect', - color: i % 2 === 0 ? `#ff${color}` : `#${color}ff`, - coordinates: - i % 2 === 0 - ? [ - [startX, startY], - [startX + 200, startY + 50], - [startX + 300, startY + 300], - [startX + 100, startY + 250], - ] - : [ - [startX, startY], - [startX + 300, startY + 300], - ], - }; -}); - export default function ImageCanvas() { - const stageWidth = window.innerWidth; - const stageHeight = window.innerHeight; + const sidebarSize = useCanvasStore((state) => state.sidebarSize); + const stageWidth = window.innerWidth * ((100 - sidebarSize) / 100) - 280; + const stageHeight = window.innerHeight - 64; const stageRef = useRef(null); const dragLayerRef = useRef(null); const scale = useRef(0); @@ -209,11 +182,6 @@ export default function ImageCanvas() { return { x: scale.current, y: scale.current }; }; - // TODO: remove mock data - useEffect(() => { - useCanvasStore.setState({ labels: mockLabels }); - }, []); - useEffect(() => { if (!stageRef.current) return; stageRef.current.container().style.cursor = drawState === 'pointer' ? 'default' : 'crosshair'; diff --git a/frontend/src/components/WorkspaceLayout/index.tsx b/frontend/src/components/WorkspaceLayout/index.tsx index 2578455..35c23e8 100644 --- a/frontend/src/components/WorkspaceLayout/index.tsx +++ b/frontend/src/components/WorkspaceLayout/index.tsx @@ -4,8 +4,48 @@ import { Label, Project } from '@/types'; import { ResizablePanelGroup, ResizablePanel } from '../ui/resizable'; import WorkspaceSidebar from '../WorkspaceSidebar'; import WorkspaceLabelBar from '../WorkspaceLabelBar'; +import { useEffect } from 'react'; +import useCanvasStore from '@/stores/useCanvasStore'; + +const mockLabels: Label[] = [ + { + id: 1, + name: 'Label 1', + color: '#FFaa33', + coordinates: [ + [700, 100], + [1200, 800], + ], + type: 'rect', + }, + { + id: 2, + name: 'Label 2', + color: '#aaFF55', + coordinates: [ + [200, 200], + [400, 200], + [500, 500], + [400, 800], + [200, 800], + [100, 500], + ], + type: 'polygon', + }, + { + id: 3, + name: 'Label 3', + color: '#77aaFF', + coordinates: [ + [1000, 1000], + [1800, 1800], + ], + type: 'rect', + }, +]; export default function WorkspaceLayout() { + const setLabels = useCanvasStore((state) => state.setLabels); const workspace: { name: string; projects: Project[] } = { name: 'Workspace-name-1', projects: [ @@ -60,29 +100,10 @@ export default function WorkspaceLayout() { }, ], }; - const labels: Label[] = [ - { - id: 1, - name: 'Label 1', - color: '#FFaa33', - coordinates: [], - type: 'rect', - }, - { - id: 2, - name: 'Label 2', - color: '#aaFF55', - coordinates: [], - type: 'rect', - }, - { - id: 3, - name: 'Label 3', - color: '#77aaFF', - coordinates: [], - type: 'rect', - }, - ]; + + useEffect(() => { + setLabels(mockLabels); + }, [setLabels]); return ( <> @@ -97,7 +118,7 @@ export default function WorkspaceLayout() {
- + diff --git a/frontend/src/components/WorkspaceSidebar/index.tsx b/frontend/src/components/WorkspaceSidebar/index.tsx index 748e9f0..c32492d 100644 --- a/frontend/src/components/WorkspaceSidebar/index.tsx +++ b/frontend/src/components/WorkspaceSidebar/index.tsx @@ -3,8 +3,11 @@ import { ResizableHandle, ResizablePanel } from '../ui/resizable'; import ProjectStructure from './ProjectStructure'; import { Button } from '../ui/button'; import { Project } from '@/types'; +import useCanvasStore from '@/stores/useCanvasStore'; export default function WorkspaceSidebar({ workspaceName, projects }: { workspaceName: string; projects: Project[] }) { + const setSidebarSize = useCanvasStore((state) => state.setSidebarSize); + return ( <> { - console.log(size); - }} + onResize={(size) => setSidebarSize(size)} >

{workspaceName}

diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 8aa87b6..84b95b4 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -9,6 +9,7 @@ import AdminMemberManage from '@/components/AdminMemberManage'; import OAuthCallback from '@/components/OAuthCallback'; import { createBrowserRouter } from 'react-router-dom'; import { Navigate } from 'react-router-dom'; +import ImageCanvas from '@/components/ImageCanvas'; export const webPath = { home: () => '/', @@ -49,7 +50,7 @@ const router = createBrowserRouter([ children: [ { index: true, - element:
workspace
, + element: , }, ], }, diff --git a/frontend/src/stores/useCanvasStore.ts b/frontend/src/stores/useCanvasStore.ts index 234cc72..72dafbe 100644 --- a/frontend/src/stores/useCanvasStore.ts +++ b/frontend/src/stores/useCanvasStore.ts @@ -2,10 +2,13 @@ import { Label } from '@/types'; import { create } from 'zustand'; interface CanvasState { + sidebarSize: number; image: string; labels: Label[]; drawState: 'pen' | 'rect' | 'pointer'; + setSidebarSize: (width: number) => void; changeImage: (image: string, labels: Label[]) => void; + setLabels: (labels: Label[]) => void; addLabel: (label: Label) => void; removeLabel: (labelId: number) => void; updateLabel: (label: Label) => void; @@ -13,11 +16,14 @@ interface CanvasState { } const useCanvasStore = create()((set) => ({ + sidebarSize: 20, image: '', labels: [], drawState: 'pointer', + setSidebarSize: (width) => set({ sidebarSize: width }), changeImage: (image: string, labels: Label[]) => set({ image, labels }), addLabel: (label: Label) => set((state) => ({ labels: [...state.labels, label] })), + setLabels: (labels) => set({ labels }), removeLabel: (labelId: number) => set((state) => ({ labels: state.labels.filter((label) => label.id !== labelId) })), updateLabel: (label: Label) => set((state) => ({ labels: state.labels.map((l) => (l.id === label.id ? label : l)) })), setDrawState: (drawState) => set({ drawState }),