fix: close final viewer integration gaps (#5)

This commit is contained in:
2026-07-29 10:14:09 +09:00
parent cadbd5fb60
commit 8ae7c45e9a
9 changed files with 196 additions and 28 deletions
+3
View File
@@ -6,7 +6,10 @@
"scripts": {
"dev": "vite --host 127.0.0.1 --port 5173 --strictPort",
"build": "tsc --noEmit && vite build",
"build:subpath:e2e": "vite build --base=/viewer-2d/ --outDir=dist-subpath",
"preview": "vite preview",
"preview:subpath:e2e": "vite preview --base=/viewer-2d/ --outDir=dist-subpath --host 127.0.0.1 --port 45173 --strictPort",
"serve:subpath:e2e": "npm run build:subpath:e2e && npm run preview:subpath:e2e",
"typecheck": "tsc --noEmit"
},
"dependencies": {
+7 -10
View File
@@ -23,8 +23,8 @@
import {
createViewer2D,
isCad2DFile,
parseCad,
type CadParseResult,
loadCad,
type CadLoadSummary,
} from '@hmwebviewer/viewer2d';
import {
assertCadByteLength,
@@ -71,11 +71,8 @@ viewer.onSelect((entity: unknown) => {
});
// ── ④ 파서 조합 ─────────────────────────────────────────────────
async function loadAndRender(buf: ArrayBuffer, name: string): Promise<CadParseResult> {
const result = await parseCad({ data: buf, name });
viewer.load(result);
viewer.resize();
return result;
async function loadAndRender(buf: ArrayBuffer, name: string): Promise<CadLoadSummary> {
return loadCad(viewer, { data: buf, name });
}
async function loadUrl(url: string, nameHint?: string) {
@@ -117,13 +114,13 @@ function fillLayers() {
}
}
async function afterLoad(name: string, result: CadParseResult) {
setStatus(`${name} · ${result.entities?.length ?? 0} entities`);
async function afterLoad(name: string, result: CadLoadSummary) {
setStatus(`${name} · ${result.entityCount} entities`);
fillLayers();
viewer.fit();
}
async function run(label: string, job: () => Promise<CadParseResult>) {
async function run(label: string, job: () => Promise<CadLoadSummary>) {
setStatus(`loading ${label}`);
try {
await afterLoad(label, await job());
@@ -29,6 +29,7 @@ export class ThreeDViewer {
private readonly onError;
private readonly fps = createFpsMeter();
private readonly adaptive;
private disposed = false;
private raf = 0;
private current: THREE.Object3D | null = null;
private outline: THREE.Group | null = null;
@@ -323,6 +324,7 @@ export class ThreeDViewer {
};
private animate = (now: number = performance.now()): void => {
if (this.disposed) return;
this.raf = requestAnimationFrame(this.animate);
this.fps.sample(now);
this.adaptive.update(this.fps.fps());
@@ -331,14 +333,20 @@ export class ThreeDViewer {
};
dispose(): void {
if (this.disposed) return;
this.disposed = true;
cancelAnimationFrame(this.raf);
this.raf = 0;
window.removeEventListener('resize', this.onResize);
this.controls.dispose();
this.clearOutline();
if (this.current) this.disposeObject(this.current);
this.current = null;
this.fps.el.remove();
this.renderer.dispose();
this.renderer.forceContextLoss();
this.renderer.domElement.remove();
this.scene.clear();
}
/** Orbit the camera to azimuth (radians) around the model — used by tools/prerender.mjs. */