diff --git a/src/components/canvas/CanvasUI.tsx b/src/components/canvas/CanvasUI.tsx
index ca9036e..e994c03 100644
--- a/src/components/canvas/CanvasUI.tsx
+++ b/src/components/canvas/CanvasUI.tsx
@@ -10,6 +10,8 @@ type CanvasUIProps = {
onImageDelete: () => void;
hasImage: boolean;
colors: string[];
+ onZoomIn: () => void;
+ onZoomOut: () => void;
};
export default function CanvasUI(props: CanvasUIProps) {
diff --git a/src/components/canvas/CanvasUIMobile.tsx b/src/components/canvas/CanvasUIMobile.tsx
index 37bb78d..6f4c81f 100644
--- a/src/components/canvas/CanvasUIMobile.tsx
+++ b/src/components/canvas/CanvasUIMobile.tsx
@@ -17,6 +17,8 @@ type CanvasUIProps = {
onImageDelete: () => void;
hasImage: boolean;
colors: string[];
+ onZoomIn: () => void;
+ onZoomOut: () => void;
};
export default function CanvasUIMobile({
@@ -26,6 +28,8 @@ export default function CanvasUIMobile({
onImageDelete,
hasImage,
colors,
+ onZoomIn,
+ onZoomOut,
}: CanvasUIProps) {
const [isPressed, setIsPressed] = useState(false);
const [showConfirmEffect, setShowConfirmEffect] = useState(false);
@@ -319,10 +323,52 @@ export default function CanvasUIMobile({
)}
{/* 좌표 표시창 */}
-
+
{hoverPos ? `(${hoverPos.x}, ${hoverPos.y})` : 'OutSide'}
+ {/* 확대/축소 버튼 */}
+
+
{/* 팔레트 */}
{
+ const canvas = renderCanvasRef.current;
+ if (!canvas) return;
+
+ const centerX = canvas.clientWidth / 2;
+ const centerY = canvas.clientHeight / 2;
+
+ const xs = (centerX - viewPosRef.current.x) / scaleRef.current;
+ const ys = (centerY - viewPosRef.current.y) / scaleRef.current;
+
+ const newScale = Math.max(
+ MIN_SCALE,
+ Math.min(MAX_SCALE, scaleRef.current * scaleChange)
+ );
+
+ scaleRef.current = newScale;
+ viewPosRef.current.x = centerX - xs * scaleRef.current;
+ viewPosRef.current.y = centerY - ys * scaleRef.current;
+
+ draw();
+ updateOverlay(centerX, centerY);
+ },
+ [draw, updateOverlay]
+ );
+
+ const handleZoomIn = useCallback(() => {
+ zoomCanvas(1.2);
+ }, [zoomCanvas]);
+
+ const handleZoomOut = useCallback(() => {
+ zoomCanvas(1 / 1.2);
+ }, [zoomCanvas]);
+
const handleCooltime = useCallback(() => {
startCooldown(10);
}, [startCooldown]);
@@ -1070,6 +1104,8 @@ function PixelCanvas({
onImageAttach={handleImageAttach}
onImageDelete={cancelImage}
hasImage={!!imageCanvasRef.current}
+ onZoomIn={handleZoomIn}
+ onZoomOut={handleZoomOut}
/>
)}
{showImageControls && !isImageFixed && (
diff --git a/src/components/toast/InstructionsToast.tsx b/src/components/toast/InstructionsToast.tsx
index 9410fa1..c07777a 100644
--- a/src/components/toast/InstructionsToast.tsx
+++ b/src/components/toast/InstructionsToast.tsx
@@ -2,7 +2,9 @@ import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
export const showInstructionsToast = () => {
- toast(
+ const isMobile = window.innerWidth < 768; // 모바일 기기 판단 기준
+
+ const mobileInstructions = (
How to Play
@@ -20,8 +22,8 @@ export const showInstructionsToast = () => {
- 마우스 좌클릭:{' '}
- 픽셀 선택
+ 픽셀 선택:{' '}
+ 탭 (클릭)
@@ -39,8 +41,10 @@ export const showInstructionsToast = () => {
/>
- 마우스 휠:{' '}
- 확대/축소
+ 확대/축소:{' '}
+
+ 오른쪽 하단 +/- 버튼 또는 두 손가락 핀치
+
@@ -57,7 +61,19 @@ export const showInstructionsToast = () => {
- {/*
+
+ );
+
+ const desktopInstructions = (
+
+
How to Play
+
+
*/}
+
+
+
+ 마우스 좌클릭:{' '}
+ 픽셀 선택
+
+
+
+
+
+ 마우스 휠:{' '}
+ 확대/축소
+
+
+
+
마우스 좌클릭 후 드래그:
@@ -96,17 +150,18 @@ export const showInstructionsToast = () => {
좌상단 이미지 버튼 클릭
-
,
- {
- position: 'top-center',
- autoClose: 5000,
- hideProgressBar: true,
- closeOnClick: true,
- pauseOnHover: true,
- draggable: true,
- progress: undefined,
- theme: 'dark',
- style: { backgroundColor: '#1f2937', color: 'white' },
- }
+
);
+
+ toast(isMobile ? mobileInstructions : desktopInstructions, {
+ position: 'top-center',
+ autoClose: 5000,
+ hideProgressBar: true,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ theme: 'dark',
+ style: { backgroundColor: '#1f2937', color: 'white' },
+ });
};
diff --git a/src/hooks/useSocket.ts b/src/hooks/useSocket.ts
index 68f3a61..70e2ec7 100644
--- a/src/hooks/useSocket.ts
+++ b/src/hooks/useSocket.ts
@@ -20,7 +20,7 @@ export const useSocket = (
canvas_id: string | undefined,
onCooldownReceived?: (cooldown: CooldownData) => void
) => {
- const { accessToken } = useAuthStore();
+ const { accessToken, user } = useAuthStore();
const pixelCallbackRef = useRef(onPixelReceived);
const cooldownCallbackRef = useRef(onCooldownReceived);
const [isConnected, setIsConnected] = useState(false);
@@ -78,7 +78,7 @@ export const useSocket = (
socketService.disconnect();
setIsConnected(false);
};
- }, [canvas_id, accessToken]);
+ }, [canvas_id, accessToken, user]);
const sendPixel = (pixel: PixelData) => {
if (!canvas_id) return;