Skip to content

Commit 759d0a2

Browse files
committed
fixes to demo page
1 parent 20438af commit 759d0a2

File tree

4 files changed

+210
-68
lines changed

4 files changed

+210
-68
lines changed

client/public/ar-demo.html

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6+
<title>AR.js Demo</title>
7+
<script src="https://aframe.io/releases/1.4.2/aframe.min.js"></script>
8+
<script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script>
9+
<style>
10+
body {
11+
margin: 0;
12+
overflow: hidden;
13+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
14+
}
15+
16+
#back-button {
17+
position: fixed;
18+
top: 16px;
19+
left: 16px;
20+
z-index: 99999;
21+
background: rgba(255, 255, 255, 0.95);
22+
border: none;
23+
border-radius: 8px;
24+
padding: 10px 16px;
25+
font-size: 14px;
26+
font-weight: 500;
27+
color: #1a1a1a;
28+
cursor: pointer;
29+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
30+
display: flex;
31+
align-items: center;
32+
gap: 8px;
33+
transition: all 0.2s;
34+
}
35+
36+
#back-button:hover {
37+
background: rgba(255, 255, 255, 1);
38+
transform: translateY(-1px);
39+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
40+
}
41+
42+
#back-button:active {
43+
transform: translateY(0);
44+
}
45+
46+
#instructions {
47+
position: fixed;
48+
top: 16px;
49+
right: 16px;
50+
z-index: 99999;
51+
background: rgba(0, 0, 0, 0.9);
52+
color: white;
53+
border-radius: 8px;
54+
padding: 12px;
55+
max-width: 200px;
56+
font-size: 11px;
57+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
58+
backdrop-filter: blur(10px);
59+
border: 1px solid rgba(255, 255, 255, 0.2);
60+
}
61+
62+
#instructions h3 {
63+
margin: 0 0 8px 0;
64+
font-size: 13px;
65+
font-weight: 600;
66+
display: flex;
67+
align-items: center;
68+
gap: 6px;
69+
}
70+
71+
#instructions ol {
72+
margin: 0;
73+
padding-left: 16px;
74+
}
75+
76+
#instructions li {
77+
margin: 4px 0;
78+
line-height: 1.4;
79+
}
80+
81+
#instructions a {
82+
color: #60a5fa;
83+
text-decoration: underline;
84+
}
85+
86+
.a-canvas {
87+
position: fixed !important;
88+
top: 0 !important;
89+
left: 0 !important;
90+
width: 100% !important;
91+
height: 100% !important;
92+
}
93+
</style>
94+
</head>
95+
<body>
96+
<button id="back-button" onclick="goBack()">
97+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
98+
<path d="M19 12H5M12 19l-7-7 7-7"/>
99+
</svg>
100+
Back
101+
</button>
102+
103+
<div id="instructions">
104+
<h3>
105+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
106+
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/>
107+
<circle cx="12" cy="13" r="4"/>
108+
</svg>
109+
AR Instructions
110+
</h3>
111+
<ol>
112+
<li>Allow camera access</li>
113+
<li>Print <a href="https://raw.githubusercontent.com/AR-js-org/AR.js/master/data/images/hiro.png" target="_blank">Hiro marker</a></li>
114+
<li>Point camera at marker</li>
115+
</ol>
116+
</div>
117+
118+
<a-scene
119+
embedded
120+
arjs="sourceType: webcam; debugUIEnabled: false; detectionMode: mono_and_matrix; matrixCodeType: 3x3;"
121+
vr-mode-ui="enabled: false"
122+
renderer="logarithmicDepthBuffer: true; precision: medium;">
123+
124+
<a-marker preset="hiro">
125+
<a-box
126+
position="0 0.5 0"
127+
material="color: #FF0000; opacity: 0.9;"
128+
animation="property: rotation; to: 0 360 0; loop: true; dur: 3000; easing: linear">
129+
</a-box>
130+
<a-text
131+
value="Hello AR!"
132+
position="0 1.5 0"
133+
align="center"
134+
color="#FFFFFF"
135+
scale="2 2 2">
136+
</a-text>
137+
</a-marker>
138+
139+
<a-entity camera></a-entity>
140+
</a-scene>
141+
142+
<script>
143+
function goBack() {
144+
// Stop all video streams before navigating
145+
const videos = document.querySelectorAll('video');
146+
videos.forEach(video => {
147+
if (video.srcObject) {
148+
const stream = video.srcObject;
149+
stream.getTracks().forEach(track => track.stop());
150+
video.srcObject = null;
151+
}
152+
});
153+
154+
// Get the base path from the current URL
155+
const path = window.location.pathname;
156+
const basePath = path.substring(0, path.lastIndexOf('/'));
157+
158+
// Navigate back to home
159+
window.location.href = basePath + '/';
160+
}
161+
162+
// Stop camera when page is being unloaded
163+
window.addEventListener('beforeunload', () => {
164+
const videos = document.querySelectorAll('video');
165+
videos.forEach(video => {
166+
if (video.srcObject) {
167+
const stream = video.srcObject;
168+
stream.getTracks().forEach(track => track.stop());
169+
}
170+
});
171+
});
172+
</script>
173+
</body>
174+
</html>

client/src/pages/Home.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,12 @@ function DemosSection() {
220220
</CardDescription>
221221
</CardHeader>
222222
<CardContent>
223-
<Link href="/demos/ar">
223+
<a href={`${window.location.origin}${appConfig.deployment.basePath}ar-demo.html`} target="_blank" rel="noopener noreferrer">
224224
<Button className="w-full gap-2">
225225
Launch Demo
226226
<ExternalLink className="w-4 h-4" />
227227
</Button>
228-
</Link>
228+
</a>
229229
</CardContent>
230230
</Card>
231231

client/src/pages/demos/AFrameDemoPage.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,44 @@ import { Button } from '@/components/ui/button';
55

66
export default function AFrameDemoPage() {
77
useEffect(() => {
8+
// Save original viewport
9+
const originalViewport = document.querySelector('meta[name="viewport"]');
10+
const originalContent = originalViewport?.getAttribute('content') || '';
11+
12+
// Set viewport for A-Frame (prevent zoom but allow user scaling)
13+
if (originalViewport) {
14+
originalViewport.setAttribute('content', 'width=device-width, initial-scale=1.0, user-scalable=yes');
15+
}
16+
817
// Load A-Frame script
918
const script = document.createElement('script');
1019
script.src = 'https://aframe.io/releases/1.4.2/aframe.min.js';
1120
script.async = true;
1221
document.head.appendChild(script);
1322

23+
// Cleanup function
1424
return () => {
15-
// Cleanup
25+
// Remove A-Frame script
1626
script.remove();
27+
28+
// Restore original viewport
29+
if (originalViewport && originalContent) {
30+
originalViewport.setAttribute('content', originalContent);
31+
}
32+
33+
// Remove any A-Frame injected elements
34+
const aframeStyles = document.querySelectorAll('style[data-aframe]');
35+
aframeStyles.forEach(style => style.remove());
36+
37+
// Force viewport reset
38+
if (originalViewport) {
39+
originalViewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes');
40+
}
1741
};
1842
}, []);
1943

2044
const aframeHTML = `
21-
<a-scene>
45+
<a-scene embedded style="width: 100%; height: 100vh;">
2246
<a-sky color="#ECECEC"></a-sky>
2347
2448
<a-box
Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,19 @@
11
import { useEffect } from 'react';
2-
import { Link } from 'wouter';
3-
import { ArrowLeft } from 'lucide-react';
4-
import { Button } from '@/components/ui/button';
2+
import { appConfig } from '@/config/app.config';
53

64
export default function ARDemoPage() {
75
useEffect(() => {
8-
// Load A-Frame first
9-
const aframeScript = document.createElement('script');
10-
aframeScript.src = 'https://aframe.io/releases/1.4.2/aframe.min.js';
11-
aframeScript.async = true;
12-
document.head.appendChild(aframeScript);
13-
14-
// Then load AR.js
15-
aframeScript.onload = () => {
16-
const arScript = document.createElement('script');
17-
arScript.src = 'https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js';
18-
arScript.async = true;
19-
document.head.appendChild(arScript);
20-
};
21-
22-
return () => {
23-
// Cleanup
24-
aframeScript.remove();
25-
};
6+
// Redirect to standalone HTML page
7+
const basePath = appConfig.deployment.basePath || '';
8+
window.location.href = `${basePath}ar-demo.html`;
269
}, []);
2710

28-
const arHTML = `
29-
<a-scene
30-
embedded
31-
arjs="sourceType: webcam; debugUIEnabled: false; detectionMode: mono_and_matrix; matrixCodeType: 3x3;">
32-
<a-marker preset="hiro">
33-
<a-box
34-
position="0 0.5 0"
35-
material="color: red;"
36-
animation="property: rotation; to: 0 360 0; loop: true; dur: 3000">
37-
</a-box>
38-
<a-text
39-
value="Hello AR!"
40-
position="0 1.5 0"
41-
align="center"
42-
color="#FFF">
43-
</a-text>
44-
</a-marker>
45-
<a-entity camera></a-entity>
46-
</a-scene>
47-
`;
48-
4911
return (
50-
<div className="min-h-screen bg-background">
51-
<div className="fixed top-4 left-4 z-50">
52-
<Link href="/">
53-
<Button variant="secondary" size="sm" className="gap-2">
54-
<ArrowLeft className="w-4 h-4" />
55-
Back to Home
56-
</Button>
57-
</Link>
58-
</div>
59-
60-
<div className="fixed top-4 right-4 z-50 bg-black/70 text-white px-4 py-2 rounded-lg text-sm max-w-xs">
61-
<p className="font-semibold mb-1">AR Instructions:</p>
62-
<ol className="text-xs space-y-1 list-decimal list-inside">
63-
<li>Allow camera access</li>
64-
<li>Print/display <a href="https://raw.githubusercontent.com/AR-js-org/AR.js/master/data/images/hiro.png" target="_blank" rel="noopener noreferrer" className="underline">Hiro marker</a></li>
65-
<li>Point camera at marker</li>
66-
</ol>
12+
<div className="min-h-screen bg-background flex items-center justify-center">
13+
<div className="text-center">
14+
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto mb-4"></div>
15+
<p className="text-muted-foreground">Loading AR experience...</p>
6716
</div>
68-
69-
<div
70-
className="w-full h-screen"
71-
dangerouslySetInnerHTML={{ __html: arHTML }}
72-
/>
7317
</div>
7418
);
7519
}

0 commit comments

Comments
 (0)