Spaces:
Running
Running
File size: 4,139 Bytes
31a2d08 62c50cd 5679415 31a2d08 c99cc8d 31a2d08 5679415 31a2d08 c99cc8d 5679415 c99cc8d 31a2d08 c99cc8d 31a2d08 c99cc8d 62c50cd c99cc8d 31a2d08 5412da9 31a2d08 c99cc8d 31a2d08 5743069 31a2d08 d10886e 5679415 d10886e 31a2d08 5743069 31a2d08 c99cc8d 62c50cd e7b5357 153165c 31a2d08 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
<script lang="ts">
import { onMount, onDestroy } from "svelte";
import type { IViewer } from "./viewers/IViewer";
import { createViewer } from "./viewers/ViewerFactory";
import { ArrowLeft, Cube, WatsonHealth3DPrintMesh } from "carbon-icons-svelte";
import type { Config } from "./utils/Config";
import { getConfig } from "./utils/getConfig";
interface Scene {
name: string;
url: string;
thumbnail: string;
}
export let modelName: string;
export let scene: Scene;
export let onBack: () => void;
let container: HTMLDivElement;
let canvas: HTMLCanvasElement;
let overlay: HTMLDivElement;
let loadingBarFill: HTMLDivElement;
let viewer: IViewer;
let displayName: string;
async function loadScene() {
overlay.style.display = "flex";
displayName = (await getConfig(modelName)).DisplayName || modelName;
viewer = await createViewer(scene.url, canvas, (progress) => {
loadingBarFill.style.width = `${progress * 100}%`;
});
window.addEventListener("resize", handleResize);
window.addEventListener("keydown", handleKeyDown);
handleResize();
overlay.style.display = "none";
}
function handleResize() {
if (!canvas || !container) return;
requestAnimationFrame(() => {
canvas.width = container.clientWidth;
canvas.height = container.clientHeight;
});
}
function handleKeyDown(e: KeyboardEvent) {
if (e.code === "KeyP") {
capture();
}
}
async function capture() {
const data = await viewer.capture();
if (!data) {
console.error("Failed to capture screenshot");
return;
}
const a = document.createElement("a");
a.href = data;
a.download = `${scene.name}.png`;
a.click();
}
onMount(loadScene);
onDestroy(() => {
viewer?.dispose();
if (typeof window !== "undefined") {
window.removeEventListener("resize", handleResize);
window.removeEventListener("keydown", handleKeyDown);
}
});
</script>
<div class="header">
<div class="back" aria-label="Back" aria-hidden="true" on:click={onBack}>
<ArrowLeft size={24} />
</div>
<div class="spacer" />
<button class="title-button" on:click={loadScene}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<h2>
{#if displayName}
<span class="muted" on:click={onBack}>{displayName}/</span>{scene.name.length > 16
? `${scene.name.slice(0, 16)}...`
: scene.name}
{:else}
Loading...
{/if}
</h2>
</button>
<div class="desktop-spacer" />
</div>
<div class="canvas-container" bind:this={container}>
<div bind:this={overlay} class="loading-overlay">
<div class="loading-bar">
<div bind:this={loadingBarFill} class="loading-bar-fill" />
</div>
</div>
<canvas class="viewer-canvas" bind:this={canvas} width={800} height={600}> </canvas>
<div class="stats">
{#if viewer}
<p>vertex count: {viewer.vertexCount}</p>
{/if}
</div>
{#if viewer && !viewer.topoOnly}
<div class="mode-toggle">
<label>
<input
type="radio"
name="modeB"
value="default"
checked
on:change={() => viewer.setRenderMode("default")}
/>
<Cube class="mode-toggle-icon" />
</label>
<label>
<input
type="radio"
name="modeB"
value="wireframe"
on:change={() => viewer.setRenderMode("wireframe")}
/>
<WatsonHealth3DPrintMesh class="mode-toggle-icon" />
</label>
</div>
{/if}
</div>
|