Skip to content

Commit 0b55c4a

Browse files
committed
feat: update index.html for ARToolKit plugin integration with improved UI and event handling
1 parent 327b534 commit 0b55c4a

File tree

1 file changed

+149
-184
lines changed

1 file changed

+149
-184
lines changed

examples/simple-marker/index.html

Lines changed: 149 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -1,191 +1,156 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html lang="en">
33
<head>
4-
<meta charset="UTF-8">
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>ARToolKit Plugin - Simple Marker Example</title>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>Simple Marker Example - ARToolKit Plugin</title>
77
<style>
8-
body {
9-
margin: 0;
10-
padding: 20px;
11-
font-family: Arial, sans-serif;
12-
background: #f0f0f0;
13-
}
14-
15-
.container {
16-
max-width: 1200px;
17-
margin: 0 auto;
18-
}
19-
20-
h1 {
21-
color: #333;
22-
}
23-
24-
.info {
25-
background: #fff;
26-
padding: 15px;
27-
border-radius: 5px;
28-
margin-bottom: 20px;
29-
border-left: 4px solid #007bff;
30-
}
31-
32-
.video-container {
33-
position: relative;
34-
background: #000;
35-
border-radius: 5px;
36-
overflow: hidden;
37-
margin-bottom: 20px;
38-
}
39-
40-
#video {
41-
width: 100%;
42-
max-width: 640px;
43-
display: block;
44-
}
45-
46-
.controls {
47-
background: #fff;
48-
padding: 15px;
49-
border-radius: 5px;
50-
margin-bottom: 20px;
51-
}
52-
53-
button {
54-
background: #007bff;
55-
color: white;
56-
border: none;
57-
padding: 10px 20px;
58-
border-radius: 5px;
59-
cursor: pointer;
60-
font-size: 16px;
61-
margin-right: 10px;
62-
}
63-
64-
button:hover {
65-
background: #0056b3;
66-
}
67-
68-
button:disabled {
69-
background: #ccc;
70-
cursor: not-allowed;
71-
}
72-
73-
.console {
74-
background: #1e1e1e;
75-
color: #d4d4d4;
76-
padding: 15px;
77-
border-radius: 5px;
78-
font-family: 'Courier New', monospace;
79-
font-size: 12px;
80-
max-height: 300px;
81-
overflow-y: auto;
82-
margin-bottom: 20px;
83-
}
84-
85-
.console-line {
86-
margin-bottom: 5px;
87-
padding: 2px 0;
88-
}
89-
90-
.console-line.info {
91-
color: #4ec9b0;
92-
}
93-
94-
.console-line.error {
95-
color: #f48771;
96-
}
97-
98-
.console-line.warn {
99-
color: #dcdcaa;
100-
}
101-
102-
.status {
103-
background: #fff;
104-
padding: 15px;
105-
border-radius: 5px;
106-
margin-bottom: 20px;
107-
}
108-
109-
.status-item {
110-
margin: 5px 0;
111-
}
112-
113-
.badge {
114-
display: inline-block;
115-
padding: 3px 8px;
116-
border-radius: 3px;
117-
font-size: 12px;
118-
font-weight: bold;
119-
margin-left: 10px;
120-
}
121-
122-
.badge.success {
123-
background: #28a745;
124-
color: white;
125-
}
126-
127-
.badge.warning {
128-
background: #ffc107;
129-
color: #333;
130-
}
131-
132-
.badge.danger {
133-
background: #dc3545;
134-
color: white;
135-
}
8+
body { font-family: Arial, sans-serif; max-width: 900px; margin: 40px auto; padding: 20px; }
9+
h1 { color: #333; }
10+
.status { padding: 10px; margin: 10px 0; border-radius: 4px; background-color: #f0f0f0; }
11+
.status.success { background-color: #d4edda; color: #155724; }
12+
.status.error { background-color: #f8d7da; color: #721c24; }
13+
.log { background:#f5f5f5; padding:10px; border-radius:4px; max-height:300px; overflow-y:auto; font-family:monospace; font-size:12px; }
14+
button { padding:10px 16px; margin:6px; cursor:pointer; border:none; border-radius:4px; background:#007bff; color:white; }
15+
button[disabled] { background:#999; cursor:default; }
16+
#video { display:none; }
13617
</style>
13718
</head>
13819
<body>
139-
<div class="container">
140-
<h1>ARToolKit Plugin - Simple Marker Detection Example</h1>
141-
142-
<div class="info">
143-
<p><strong>Instructions:</strong></p>
144-
<ol>
145-
<li>Click "Start Camera" to begin webcam capture</li>
146-
<li>Show an ARToolKit marker to the camera</li>
147-
<li>Detection results will appear in the console below</li>
148-
<li>Check your browser's developer console for detailed logs</li>
149-
</ol>
150-
<p><strong>Note:</strong> This example requires HTTPS or localhost to access the webcam.</p>
151-
</div>
152-
153-
<div class="controls">
154-
<button id="startBtn">Start Camera</button>
155-
<button id="stopBtn" disabled>Stop Camera</button>
156-
</div>
157-
158-
<div class="status">
159-
<h3>Status</h3>
160-
<div class="status-item">
161-
Camera: <span id="cameraStatus" class="badge warning">Not started</span>
162-
</div>
163-
<div class="status-item">
164-
Plugin: <span id="pluginStatus" class="badge warning">Not initialized</span>
165-
</div>
166-
<div class="status-item">
167-
Worker: <span id="workerStatus" class="badge warning">Not ready</span>
168-
</div>
169-
<div class="status-item">
170-
Frames processed: <span id="frameCount">0</span>
171-
</div>
172-
<div class="status-item">
173-
Markers detected: <span id="markerCount">0</span>
174-
</div>
175-
</div>
176-
177-
<div class="video-container">
178-
<video id="video" autoplay playsinline></video>
179-
</div>
180-
181-
<div>
182-
<h3>Console Output</h3>
183-
<div id="console" class="console">
184-
<div class="console-line info">Ready. Click "Start Camera" to begin.</div>
185-
</div>
186-
</div>
187-
</div>
188-
189-
<script type="module" src="./script.js"></script>
20+
<h1>Simple Marker Example</h1>
21+
<p>This example demonstrates loading a pattern marker using the ARToolKit plugin.</p>
22+
23+
<div id="status" class="status">Initializing...</div>
24+
<div>
25+
<button id="startCamBtn">Start Camera</button>
26+
<button id="loadMarkerBtn" disabled>Load Marker</button>
27+
</div>
28+
29+
<h3>Event Log:</h3>
30+
<div id="log" class="log"></div>
31+
32+
<video id="video" autoplay playsinline></video>
33+
34+
<script type="module">
35+
import { ArtoolkitPlugin } from '../../src/plugin.js';
36+
37+
const statusEl = document.getElementById('status');
38+
const logEl = document.getElementById('log');
39+
const loadMarkerBtn = document.getElementById('loadMarkerBtn');
40+
const startCamBtn = document.getElementById('startCamBtn');
41+
const video = document.getElementById('video');
42+
43+
function log(message) {
44+
const ts = new Date().toISOString();
45+
const el = document.createElement('div');
46+
el.textContent = `[${ts}] ${message}`;
47+
logEl.appendChild(el);
48+
logEl.scrollTop = logEl.scrollHeight;
49+
console.log(message);
50+
}
51+
52+
function setStatus(msg, type = 'normal') {
53+
statusEl.textContent = msg;
54+
statusEl.className = 'status';
55+
if (type === 'success') statusEl.classList.add('success');
56+
if (type === 'error') statusEl.classList.add('error');
57+
}
58+
59+
// Minimal eventBus / core used by the plugin
60+
const eventBus = {
61+
_h: new Map(),
62+
on(e, h) { if (!this._h.has(e)) this._h.set(e, []); this._h.get(e).push(h); },
63+
off(e, h) { if (!this._h.has(e)) return; this._h.set(e, this._h.get(e).filter(x => x !== h)); },
64+
emit(e, p) { (this._h.get(e) || []).forEach(fn => fn(p)); }
65+
};
66+
const core = { eventBus };
67+
68+
let plugin;
69+
70+
async function start() {
71+
try {
72+
log('Creating ArtoolkitPlugin instance...');
73+
plugin = new ArtoolkitPlugin({ worker: true });
74+
await plugin.init(core);
75+
await plugin.enable();
76+
77+
// wire event handlers
78+
eventBus.on('ar:workerReady', () => {
79+
log('Worker ready');
80+
setStatus('Worker ready. Start camera and then load marker.', 'success');
81+
loadMarkerBtn.disabled = false;
82+
});
83+
84+
eventBus.on('ar:markerFound', d => log(`markerFound: ${JSON.stringify(d)}`));
85+
eventBus.on('ar:markerUpdated', d => log(`markerUpdated: ${JSON.stringify(d)}`));
86+
eventBus.on('ar:markerLost', d => log(`markerLost: ${JSON.stringify(d)}`));
87+
eventBus.on('ar:workerError', e => {
88+
log(`workerError: ${JSON.stringify(e)}`);
89+
setStatus('Worker error (see console)', 'error');
90+
});
91+
92+
// Also log detectionResult from plugin console.log (plugin logs detectionResult)
93+
setStatus('Plugin initialized. Waiting for worker...', 'normal');
94+
} catch (err) {
95+
log('Init error: ' + (err && err.message ? err.message : err));
96+
setStatus('Initialization error', 'error');
97+
}
98+
}
99+
100+
// Start camera when user clicks (to ensure user gesture)
101+
startCamBtn.addEventListener('click', async () => {
102+
try {
103+
startCamBtn.disabled = true;
104+
log('Starting camera...');
105+
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } });
106+
video.srcObject = stream;
107+
// emit engine:update frames using createImageBitmap
108+
const canvas = document.createElement('canvas');
109+
const ctx = canvas.getContext('2d');
110+
let id = 0;
111+
112+
async function tick() {
113+
if (video.videoWidth === 0) { requestAnimationFrame(tick); return; }
114+
canvas.width = video.videoWidth;
115+
canvas.height = video.videoHeight;
116+
ctx.drawImage(video, 0, 0);
117+
const imageBitmap = await createImageBitmap(canvas);
118+
// emit engine:update; plugin will transfer the ImageBitmap to the worker
119+
eventBus.emit('engine:update', { id: ++id, imageBitmap, width: canvas.width, height: canvas.height });
120+
requestAnimationFrame(tick);
121+
}
122+
requestAnimationFrame(tick);
123+
log('Camera started.');
124+
setStatus('Camera started. You can now load the marker.', 'success');
125+
} catch (err) {
126+
log('Camera error: ' + (err && err.message ? err.message : err));
127+
setStatus('Camera error', 'error');
128+
startCamBtn.disabled = false;
129+
}
130+
});
131+
132+
// Load marker button uses plugin.loadMarker(...)
133+
loadMarkerBtn.addEventListener('click', async () => {
134+
if (!plugin) return log('Plugin not ready');
135+
loadMarkerBtn.disabled = true;
136+
setStatus('Loading marker...', 'normal');
137+
try {
138+
// Use absolute/site-root-relative URL so worker can fetch it.
139+
const patternUrl = '/examples/simple-marker/data/patt.hiro';
140+
log(`Requesting loadMarker for ${patternUrl}`);
141+
const res = await plugin.loadMarker(patternUrl, 1);
142+
log(`loadMarker result: ${JSON.stringify(res)}`);
143+
setStatus(`Marker loaded (id=${res.markerId})`, 'success');
144+
} catch (err) {
145+
log('loadMarker failed: ' + (err && err.message ? err.message : err));
146+
setStatus('Failed to load marker', 'error');
147+
} finally {
148+
loadMarkerBtn.disabled = false;
149+
}
150+
});
151+
152+
// initialize plugin but don't start camera automatically
153+
start();
154+
</script>
190155
</body>
191-
</html>
156+
</html>

0 commit comments

Comments
 (0)