feat: add zoomable image canvas with detection overlays
Load OpenCV in the browser via a script tag: the bundler's CJS interop copies the module's then() onto the import namespace, which never settles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4b19c7ea4e
commit
bec28fd0c1
4 files changed
+261
-5
No files matched your search
@@ -1,12 +1,11 @@
|
||||
export type CV = typeof import('@techstark/opencv-js');
|
||||
|
||||
// Everything returns { cv }: the cv module is a thenable, so resolving with it directly never settles.
|
||||
let loading: Promise<{ cv: CV }> | null = null;
|
||||
|
||||
// Wrapped in an object: the cv module is a thenable, so resolving with it directly never settles.
|
||||
export function loadOpenCV(): Promise<{ cv: CV }> {
|
||||
loading ??= (async () => {
|
||||
const mod = (await import('@techstark/opencv-js')) as unknown as { default: CV };
|
||||
const cv = mod.default;
|
||||
const { cv } = typeof document === 'undefined' ? await importModule() : await loadScript();
|
||||
if (!cv.Mat) {
|
||||
await new Promise<void>((resolve) => {
|
||||
(cv as unknown as { onRuntimeInitialized: () => void }).onRuntimeInitialized = () => resolve();
|
||||
@@ -16,3 +15,23 @@ export function loadOpenCV(): Promise<{ cv: CV }> {
|
||||
})();
|
||||
return loading;
|
||||
}
|
||||
|
||||
/** Node (tests). The variable specifier keeps the bundler from emitting a second OpenCV chunk. */
|
||||
async function importModule(): Promise<{ cv: CV }> {
|
||||
const specifier = '@techstark/opencv-js';
|
||||
const mod = (await import(/* @vite-ignore */ specifier)) as { default: CV };
|
||||
return { cv: mod.default };
|
||||
}
|
||||
|
||||
// A script tag, not import(): bundler CJS interop copies `then` and the import never settles.
|
||||
async function loadScript(): Promise<{ cv: CV }> {
|
||||
const { default: url } = await import('@techstark/opencv-js/dist/opencv.js?url');
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = url;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = () => reject(new Error('Failed to load OpenCV'));
|
||||
document.head.append(script);
|
||||
});
|
||||
return { cv: (window as unknown as { cv: CV }).cv };
|
||||
}
|
||||
Reference in new issue
Block a user