second: open camera

This commit is contained in:
2026-06-08 16:23:24 +09:00
parent 15be996704
commit 2b4a005407
9 changed files with 352 additions and 54 deletions

View File

@@ -0,0 +1,165 @@
<script>
import { onMount, onDestroy } from 'svelte';
import { arStore } from '$lib/stores/arStore.js';
let { lat, lng } = $props();
let videoElement;
let cameraStream = null;
let cameraError = '';
async function startCamera() {
try {
cameraStream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: { ideal: 'environment' }
},
audio: false
});
if (videoElement) {
videoElement.srcObject = cameraStream;
await videoElement.play();
}
} catch (error) {
console.error('Camera error:', error);
cameraError = 'Camera could not be started.';
}
}
function stopCamera() {
if (cameraStream) {
cameraStream.getTracks().forEach((track) => track.stop());
cameraStream = null;
}
}
function exitARMode() {
stopCamera();
arStore.update((state) => ({
...state,
isARMode: false,
selectedScreenPoint: null,
composing: false,
focusedMessage: null
}));
}
onMount(() => {
startCamera();
});
onDestroy(() => {
stopCamera();
});
</script>
<div class="ar-view">
<video
bind:this={videoElement}
class="camera-video"
autoplay
playsinline
muted
></video>
<div class="ar-overlay">
<button class="back-button" onclick={exitARMode}>
Back
</button>
{#if cameraError}
<div class="camera-error">
<p>{cameraError}</p>
<p class="small">Please check camera permission in your browser.</p>
</div>
{:else}
<div class="ar-status">
<p>AR Mode</p>
<p class="small">Move your camera slowly.</p>
</div>
{/if}
</div>
</div>
<style>
.ar-view {
position: fixed;
inset: 0;
background: #000;
color: white;
z-index: 1000;
overflow: hidden;
}
.camera-video {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
background: #000;
}
.ar-overlay {
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
}
.back-button {
position: absolute;
top: 20px;
left: 16px;
z-index: 10;
padding: 10px 14px;
border: none;
border-radius: 999px;
background: rgba(255, 255, 255, 0.9);
color: #111;
font-weight: 600;
pointer-events: auto;
}
.ar-status {
position: absolute;
left: 50%;
bottom: 36px;
transform: translateX(-50%);
padding: 12px 18px;
border-radius: 999px;
background: rgba(0, 0, 0, 0.45);
backdrop-filter: blur(8px);
text-align: center;
}
.ar-status p {
margin: 0;
font-size: 14px;
}
.small {
margin-top: 4px;
font-size: 12px;
opacity: 0.75;
}
.camera-error {
position: absolute;
left: 20px;
right: 20px;
top: 50%;
transform: translateY(-50%);
padding: 20px;
border-radius: 18px;
background: rgba(255, 255, 255, 0.94);
color: #111;
text-align: center;
}
.camera-error p {
margin: 0;
}
</style>