optimized build size again (icons & camera)

This commit is contained in:
Yeicor
2024-02-17 12:05:33 +01:00
parent 92c917b230
commit 52f6349c34
8 changed files with 54 additions and 25 deletions

View File

@@ -11,13 +11,15 @@
"dependencies": { "dependencies": {
"@gltf-transform/core": "^3.10.0", "@gltf-transform/core": "^3.10.0",
"@google/model-viewer": "^3.4.0", "@google/model-viewer": "^3.4.0",
"@jamescoyle/vue-icon": "^0.1.2",
"@mdi/js": "^7.4.47",
"@mdi/svg": "^7.4.47",
"three": "^0.160.1", "three": "^0.160.1",
"three-orientation-gizmo": "https://github.com/jrj2211/three-orientation-gizmo", "three-orientation-gizmo": "https://github.com/jrj2211/three-orientation-gizmo",
"vue": "^3.4.16", "vue": "^3.4.16",
"vuetify": "^3.5.3" "vuetify": "^3.5.3"
}, },
"devDependencies": { "devDependencies": {
"@mdi/font": "^7.4.47",
"@parcel/optimizer-data-url": "2.11.0", "@parcel/optimizer-data-url": "2.11.0",
"@parcel/reporter-bundle-analyzer": "^2.11.0", "@parcel/reporter-bundle-analyzer": "^2.11.0",
"@parcel/transformer-inline-string": "2.11.0", "@parcel/transformer-inline-string": "2.11.0",

View File

@@ -1,13 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import {defineAsyncComponent, ref, Ref} from "vue"; import {defineAsyncComponent, ref, Ref} from "vue";
import Sidebar from "./models/Sidebar.vue"; import Sidebar from "./misc/Sidebar.vue";
import Loading from "./viewer/Loading.vue"; import Loading from "./misc/Loading.vue";
import ModelViewerOverlay from "./viewer/ModelViewerOverlay.vue"; import ModelViewerOverlay from "./viewer/ModelViewerOverlay.vue";
import Tools from "./tools/Tools.vue"; import Tools from "./tools/Tools.vue";
import Models from "./models/Models.vue"; import Models from "./models/Models.vue";
import {VLayout, VMain, VToolbarTitle} from "vuetify/lib/components"; import {VLayout, VMain, VToolbarTitle} from "vuetify/lib/components";
import type {ModelViewerInfo} from "./viewer/ModelViewerWrapper.vue"; import type {ModelViewerInfo} from "./viewer/ModelViewerWrapper.vue";
import {settings} from "./tools/settings"; import {settings} from "./misc/settings";
// NOTE: The ModelViewer library is big (THREE.js), so we split it and import it asynchronously // NOTE: The ModelViewer library is big (THREE.js), so we split it and import it asynchronously
const ModelViewerWrapper = defineAsyncComponent({ const ModelViewerWrapper = defineAsyncComponent({
@@ -23,11 +23,13 @@ let modelSrc: Ref<string | Uint8Array> = ref(settings.preloadModels[0]);
<template> <template>
<v-layout full-height> <v-layout full-height>
<!-- The main content of the app is the model-viewer with the SVG "2D" overlay --> <!-- The main content of the app is the model-viewer with the SVG "2D" overlay -->
<v-main id="main"> <v-main id="main">
<model-viewer-wrapper :src="modelSrc" @load-viewer="(args) => modelViewerInfo = args"/> <model-viewer-wrapper :src="modelSrc" @load-viewer="(args) => modelViewerInfo = args"/>
<model-viewer-overlay v-if="modelViewerInfo"/> <model-viewer-overlay v-if="modelViewerInfo"/>
</v-main> </v-main>
<!-- The left collapsible sidebar has the list of models --> <!-- The left collapsible sidebar has the list of models -->
<sidebar :opened-init="openSidebarsByDefault" side="left"> <sidebar :opened-init="openSidebarsByDefault" side="left">
<template #toolbar> <template #toolbar>
@@ -35,6 +37,7 @@ let modelSrc: Ref<string | Uint8Array> = ref(settings.preloadModels[0]);
</template> </template>
<models :modelViewerInfo="modelViewerInfo"/> <models :modelViewerInfo="modelViewerInfo"/>
</sidebar> </sidebar>
<!-- The right collapsible sidebar has the list of tools --> <!-- The right collapsible sidebar has the list of tools -->
<sidebar :opened-init="openSidebarsByDefault" side="right" :width="120"> <sidebar :opened-init="openSidebarsByDefault" side="right" :width="120">
<template #toolbar> <template #toolbar>
@@ -42,6 +45,7 @@ let modelSrc: Ref<string | Uint8Array> = ref(settings.preloadModels[0]);
</template> </template>
<tools :modelViewerInfo="modelViewerInfo"/> <tools :modelViewerInfo="modelViewerInfo"/>
</sidebar> </sidebar>
</v-layout> </v-layout>
</template> </template>

View File

@@ -21,6 +21,5 @@ const app = createApp(App)
app.use(vuetify) app.use(vuetify)
app.mount('body') app.mount('body')
// Start non-blocking loading of Vuetify and icon styles // Start non-blocking loading of Vuetify styles
import('vuetify/lib/styles/main.sass'); import('vuetify/lib/styles/main.sass');
import('@mdi/font/css/materialdesignicons.css');

View File

@@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from "vue"; import {ref} from "vue";
import {VBtn, VNavigationDrawer, VToolbar, VToolbarItems} from "vuetify/lib/components"; import {VBtn, VNavigationDrawer, VToolbar, VToolbarItems} from "vuetify/lib/components";
import {mdiClose, mdiChevronRight, mdiChevronLeft} from '@mdi/js'
import SvgIcon from '@jamescoyle/vue-icon';
const props = defineProps({ const props = defineProps({
openedInit: Boolean, openedInit: Boolean,
@@ -9,22 +11,28 @@ const props = defineProps({
}); });
let opened = ref(props.openedInit); let opened = ref(props.openedInit);
const openIcon = props.side === 'left' ? '$next' : '$prev'; const openIcon = props.side === 'left' ? mdiChevronRight : mdiChevronLeft;
</script> </script>
<template> <template>
<v-btn :icon="openIcon" @click="opened = !opened" class="open-button" :class="side"/> <v-btn icon="" @click="opened = !opened" class="open-button" :class="side">
<svg-icon type="mdi" :path="openIcon"/>
</v-btn>
<v-navigation-drawer v-model="opened" permanent :location="side" :width="props.width"> <v-navigation-drawer v-model="opened" permanent :location="side" :width="props.width">
<v-toolbar density="compact"> <v-toolbar density="compact">
<v-toolbar-items v-if="side == 'right'"> <v-toolbar-items v-if="side == 'right'">
<slot name="toolbar-items"></slot> <slot name="toolbar-items"></slot>
<v-btn icon="$close" @click="opened = !opened"/> <v-btn icon="" @click="opened = !opened">
<svg-icon type="mdi" :path="mdiClose"/>
</v-btn>
</v-toolbar-items> </v-toolbar-items>
<slot name="toolbar"></slot> <slot name="toolbar"></slot>
<v-toolbar-items v-if="side == 'left'"> <v-toolbar-items v-if="side == 'left'">
<slot name="toolbar-items"></slot> <slot name="toolbar-items"></slot>
<v-btn icon="$close" @click="opened = !opened"/> <v-btn icon="" @click="opened = !opened">
<svg-icon type="mdi" :path="mdiClose"/>
</v-btn>
</v-toolbar-items> </v-toolbar-items>
</v-toolbar> </v-toolbar>
<slot/> <slot/>

View File

@@ -3,16 +3,19 @@ import {VBtn, VIcon} from "vuetify/lib/components";
import {ref} from "vue"; import {ref} from "vue";
import OrientationGizmo from "./OrientationGizmo.vue"; import OrientationGizmo from "./OrientationGizmo.vue";
import type {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene"; import type {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene";
import {OrthographicCamera} from "three"; import {OrthographicCamera} from "three/src/cameras/OrthographicCamera";
import {mdiCrosshairsGps, mdiProjector} from '@mdi/js'
import SvgIcon from '@jamescoyle/vue-icon';
const props = defineProps({
modelViewerInfo: Object const props = defineProps<{
}); modelViewerInfo: { scene: ModelScene } | null
}>();
function syncOrthoCamera(force: boolean) { function syncOrthoCamera(force: boolean) {
if (!props.modelViewerInfo) return; if (!props.modelViewerInfo) return;
let scene: ModelScene = props.modelViewerInfo.scene let scene = props.modelViewerInfo.scene
let perspectiveCam = (scene as any).__perspectiveCamera; let perspectiveCam = (scene as any).__perspectiveCamera;
if (force || perspectiveCam && scene.camera != perspectiveCam) { if (force || perspectiveCam && scene.camera != perspectiveCam) {
// Get zoom level from perspective camera // Get zoom level from perspective camera
@@ -29,7 +32,7 @@ function syncOrthoCamera(force: boolean) {
let toggleProjectionText = ref('PERSP'); // Default to perspective camera let toggleProjectionText = ref('PERSP'); // Default to perspective camera
function toggleProjection() { function toggleProjection() {
if (!props.modelViewerInfo) return; if (!props.modelViewerInfo) return;
let scene: ModelScene = props.modelViewerInfo.scene let scene = props.modelViewerInfo.scene
let prevCam = scene.camera; let prevCam = scene.camera;
let wasPerspectiveCamera = prevCam.isPerspectiveCamera; let wasPerspectiveCamera = prevCam.isPerspectiveCamera;
if (wasPerspectiveCamera) { if (wasPerspectiveCamera) {
@@ -47,11 +50,15 @@ function toggleProjection() {
<template> <template>
<orientation-gizmo v-if="props.modelViewerInfo" :scene="props.modelViewerInfo.scene"/> <orientation-gizmo v-if="props.modelViewerInfo" :scene="props.modelViewerInfo.scene"/>
<v-btn icon="mdi-projector" @click="toggleProjection"><span class="icon-detail">{{ toggleProjectionText }}</span> <v-btn icon="" @click="toggleProjection"><span class="icon-detail">{{ toggleProjectionText }}</span>
<v-icon icon="mdi-projector"></v-icon> <svg-icon type="mdi" :path="mdiProjector"></svg-icon>
</v-btn>
<v-btn icon="" @click=""> <!-- TODO: Center camera -->
<svg-icon type="mdi" :path="mdiCrosshairsGps"/>
</v-btn> </v-btn>
</template> </template>
<!--suppress CssUnusedSymbol -->
<style> <style>
.icon-detail { .icon-detail {
position: absolute; position: absolute;
@@ -62,7 +69,7 @@ function toggleProjection() {
margin: auto; margin: auto;
} }
.icon-detail + .v-icon { .icon-detail + svg {
position: relative; position: relative;
top: 5px; top: 5px;
} }

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import {settings} from "../tools/settings"; import {settings} from "../misc/settings";
import {ModelViewerElement} from '@google/model-viewer'; import {ModelViewerElement} from '@google/model-viewer';
import {onMounted, ref} from "vue"; import {onMounted, ref} from "vue";
import {$scene} from "@google/model-viewer/lib/model-viewer-base"; import {$scene} from "@google/model-viewer/lib/model-viewer-base";
@@ -28,7 +28,6 @@ onMounted(() => {
</script> </script>
<template> <template>
<!--suppress VueMissingComponentImportInspection -->
<model-viewer ref="viewer" <model-viewer ref="viewer"
style="width: 100%; height: 100%" :src="props.src" alt="The 3D model(s)" camera-controls style="width: 100%; height: 100%" :src="props.src" alt="The 3D model(s)" camera-controls
camera-orbit="30deg 75deg auto" max-camera-orbit="Infinity 180deg auto" camera-orbit="30deg 75deg auto" max-camera-orbit="Infinity 180deg auto"

View File

@@ -44,6 +44,11 @@
"@monogrid/gainmap-js" "^3.0.1" "@monogrid/gainmap-js" "^3.0.1"
lit "^2.7.2" lit "^2.7.2"
"@jamescoyle/vue-icon@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz#b9e254187de6716b81bf9e0e8400ec012231bd05"
integrity sha512-KFrImXx5TKIi6iQXlnyLEBl4rNosNKbTeRnr70ucTdUaciVmd9qK9d/pZAaKt1Ob/8xNnX2GMp8LisyHdKtEgw==
"@jridgewell/sourcemap-codec@^1.4.15": "@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15" version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
@@ -103,10 +108,15 @@
resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.8.5.tgz#8233e8762440b0f4632c47a09b1b6f23de8b934c" resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.8.5.tgz#8233e8762440b0f4632c47a09b1b6f23de8b934c"
integrity sha512-4wvrf5BgnR8RpogHhtpCPJMKBmvyZPhhUtEwMJbXh0ni2BucpfF07jlmyM11zRqQ2XIq6PbC2j7W7UCCcm1rRQ== integrity sha512-4wvrf5BgnR8RpogHhtpCPJMKBmvyZPhhUtEwMJbXh0ni2BucpfF07jlmyM11zRqQ2XIq6PbC2j7W7UCCcm1rRQ==
"@mdi/font@^7.4.47": "@mdi/js@^7.4.47":
version "7.4.47" version "7.4.47"
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-7.4.47.tgz#2ae522867da3a5c88b738d54b403eb91471903af" resolved "https://registry.yarnpkg.com/@mdi/js/-/js-7.4.47.tgz#7d8a4edc9631bffeed80d1ec784f9beae559a76a"
integrity sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw== integrity sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==
"@mdi/svg@^7.4.47":
version "7.4.47"
resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-7.4.47.tgz#f8e5516aae129764a76d1bb2f27e55bee03e6e90"
integrity sha512-WQ2gDll12T9WD34fdRFgQVgO8bag3gavrAgJ0frN4phlwdJARpE6gO1YvLEMJR0KKgoc+/Ea/A0Pp11I00xBvw==
"@mischnic/json-sourcemap@^0.1.0": "@mischnic/json-sourcemap@^0.1.0":
version "0.1.1" version "0.1.1"