1+ <!doctype html>
2+ < meta charset ="utf-8 " />
3+ < body >
4+ < h1 > Browser smoke test (ImageBitmap transfer)</ h1 >
5+
6+ < p > This is a simple example to run in a browser (served via http(s)) to exercise ImageBitmap transfer:
7+
8+ 1. Create an `index.html` and include a small script that:
9+ - obtains getUserMedia({ video: true })
10+ - creates a hidden canvas and draws video frames into it
11+ - uses `createImageBitmap(canvas)` to create an ImageBitmap
12+ - emits engine.update events with `{ id, imageBitmap, width, height }`
13+ - listens to `ar:markerFound`, `ar:markerUpdated`, `ar:markerLost` events
14+
15+ 2. Ensure the plugin is initialized in a browser environment and registered with an engine object exposing `eventBus` with `on`/`emit`.
16+ </ p >
17+ < video id ="v " autoplay playsinline style ="display:none "> </ video >
18+ < script type ="module ">
19+ import { ArtoolkitPlugin } from '../src/plugin.js' ;
20+
21+ const eventBus = {
22+ _h : new Map ( ) ,
23+ on ( e , h ) { if ( ! this . _h . has ( e ) ) this . _h . set ( e , [ ] ) ; this . _h . get ( e ) . push ( h ) ; } ,
24+ off ( e , h ) { if ( ! this . _h . has ( e ) ) return ; this . _h . set ( e , this . _h . get ( e ) . filter ( x => x !== h ) ) ; } ,
25+ emit ( e , p ) { ( this . _h . get ( e ) || [ ] ) . forEach ( fn => fn ( p ) ) ; }
26+ } ;
27+
28+ const core = { eventBus } ;
29+ const plugin = new ArtoolkitPlugin ( { worker : true } ) ;
30+ await plugin . init ( core ) ;
31+ await plugin . enable ( ) ;
32+
33+ eventBus . on ( 'ar:workerReady' , ( ) => console . log ( 'worker ready' ) ) ;
34+ eventBus . on ( 'ar:markerFound' , d => console . log ( 'FOUND' , d ) ) ;
35+ eventBus . on ( 'ar:markerUpdated' , d => console . log ( 'UPDATED' , d ) ) ;
36+ eventBus . on ( 'ar:markerLost' , d => console . log ( 'LOST' , d ) ) ;
37+
38+ const video = document . getElementById ( 'v' ) ;
39+ const stream = await navigator . mediaDevices . getUserMedia ( { video : true } ) ;
40+ video . srcObject = stream ;
41+
42+ const canvas = document . createElement ( 'canvas' ) ;
43+ const ctx = canvas . getContext ( '2d' ) ;
44+
45+ let id = 0 ;
46+ function tick ( ) {
47+ if ( video . videoWidth === 0 ) {
48+ requestAnimationFrame ( tick ) ;
49+ return ;
50+ }
51+ canvas . width = video . videoWidth ;
52+ canvas . height = video . videoHeight ;
53+ ctx . drawImage ( video , 0 , 0 ) ;
54+ createImageBitmap ( canvas ) . then ( ( imageBitmap ) => {
55+ eventBus . emit ( 'engine:update' , { id : ++ id , imageBitmap, width : canvas . width , height : canvas . height } ) ;
56+ // imageBitmap will be transferred to worker; don't reuse it after emit
57+ } ) ;
58+ requestAnimationFrame ( tick ) ;
59+ }
60+ tick ( ) ;
61+ </ script >
62+ </ body >
63+ ```
64+
65+ Note: host via `npx http-server` or similar so getUserMedia works in a secure context if needed.
66+ ```
0 commit comments