Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion frontend/src/routes/$roomId/index.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createLazyFileRoute } from "@tanstack/react-router";
import type { CalendarItemWithItem } from "common/generate/adventSphereAPI.schemas";
import { useGetCalendarItemsRoomIdCalendarItems } from "common/generate/calendar-items/calendar-items";
import { useGetRoomsId } from "common/generate/room/room";
import { X } from "lucide-react";
import { Camera, X } from "lucide-react";
import { Suspense, useCallback, useMemo, useRef, useState } from "react";
import type * as THREE from "three";
import InventoryIcon from "@/components/icons/inventory";
Expand Down Expand Up @@ -63,6 +63,7 @@ function RouteComponent() {
const roomRef = useRef<THREE.Group>(null);
const placedItemsRef = useRef<THREE.Group>(null);
const tableRef = useRef<THREE.Group>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
// アイテム取得フロー
const {
phase,
Expand Down Expand Up @@ -120,6 +121,27 @@ function RouteComponent() {
setSelectedPlacedItem(null);
}, []);

// 写真撮影
const handleTakePhoto = useCallback(() => {
if (!canvasRef.current) return;

try {
// Canvas要素からBase64データURLを取得
const dataURL = canvasRef.current.toDataURL("image/png");

// ダウンロードリンクを作成して実行
const link = document.createElement("a");
link.href = dataURL;
link.download = "screenshot.png";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error("Failed to capture photo:", error);
alert("写真の保存に失敗しました。エラーを確認してください。");
}
}, []);

// 配置モード
const {
isPlacementValid,
Expand Down Expand Up @@ -284,6 +306,17 @@ function RouteComponent() {
onOpenChange={setIsInventoryDialogOpen}
onStartPlacement={startPlacementFromInventory}
/>
{!isFocusMode && !isAnyPlacementMode && (
<Button
onClick={handleTakePhoto}
className="justify-self-end z-30 self-start size-12 md:size-14 lg:size-16 rounded-full border-2 border-primary-foreground shadow-xl active:scale-95"
variant="default"
size="icon"
title="写真を撮る"
>
<Camera className="size-5 md:size-6 lg:size-7" />
</Button>
)}
{isFocusMode && !isAnyPlacementMode && (
<Button
onClick={handleExitFocusMode}
Expand Down Expand Up @@ -333,6 +366,8 @@ function RouteComponent() {
<div className="fixed inset-0 z-0">
<Suspense fallback={<Loading text="部屋を読み込み中..." />}>
<Canvas
ref={canvasRef}
gl={{ preserveDrawingBuffer: true }}
camera={{ position: [2.3, 0.5, 2], fov: 45 }}
onPointerMissed={handleCloseMenu}
>
Expand Down