second: open camera
This commit is contained in:
165
src/lib/components/ARView.svelte
Normal file
165
src/lib/components/ARView.svelte
Normal 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>
|
||||
Reference in New Issue
Block a user