File size: 2,951 Bytes
31a2d08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c99cc8d
 
31a2d08
 
 
 
c99cc8d
 
 
 
31a2d08
 
 
c99cc8d
31a2d08
 
 
 
c99cc8d
 
 
 
 
 
31a2d08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c99cc8d
 
 
 
31a2d08
 
 
 
 
 
 
5743069
31a2d08
 
 
 
 
5743069
31a2d08
 
c99cc8d
 
 
 
 
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
<script lang="ts">
    import { onMount, onDestroy } from "svelte";
    import type { IViewer } from "./viewers/IViewer";
    import { createViewer } from "./viewers/ViewerFactory";
    import ArrowLeft from "carbon-icons-svelte/lib/ArrowLeft.svelte";

    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;

    async function loadScene() {
        overlay.style.display = "flex";
        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(() => {
            const maxWidth = container.clientHeight * (16 / 9);
            const maxHeight = container.clientWidth * (9 / 16);
            canvas.width = Math.min(container.clientWidth, maxWidth);
            canvas.height = Math.min(container.clientHeight, maxHeight);
        });
    }

    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 = "screenshot.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><span class="muted" on:click={onBack}>{modelName}/</span>{scene.name}</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 bind:this={canvas} width={800} height={600} />
</div>