150 lines
5.0 KiB
Vue
150 lines
5.0 KiB
Vue
<script setup lang="ts">
|
|
import { reactive, ref, watch } from 'vue';
|
|
import type { Ref } from 'vue'
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
import { Vector3 } from 'three';
|
|
import { TresCanvas } from '@tresjs/core';
|
|
import { OrbitControls, Stats } from '@tresjs/cientos'
|
|
import '@tresjs/leches/styles'
|
|
|
|
import LoadModels from './load_models.vue'
|
|
import Sidebar from '../sidebar.vue'
|
|
import { PROMOBG } from '../../constants';
|
|
import { usePromoSidebar } from '../../stores/promo_sidebar';
|
|
import { useLoading } from '../../stores/loading';
|
|
import { useRawData } from '../../stores/raw_data';
|
|
import { usePromoScene } from '../../stores/promo_scene';
|
|
|
|
import icon_enter from '../../assets/btn/enter.svg';
|
|
import icon_right from '../../assets/btn/right_sm.svg';
|
|
import icon_left from '../../assets/btn/left_sm.svg';
|
|
import icon_plus from '../../assets/btn/plus_lg.svg';
|
|
|
|
const minPan = ref(new Vector3(-2, -2, -2))
|
|
const maxPan = ref(new Vector3(2, 2, 2))
|
|
const _v = new Vector3();
|
|
const onChange = (e: any) => {
|
|
if (e.target) {
|
|
_v.copy(e.target);
|
|
e.target.clamp(minPan.value, maxPan.value);
|
|
_v.sub(e.target);
|
|
camera.value.position.sub(_v);
|
|
}
|
|
}
|
|
const loadedPan = (max: any, min: any) => {
|
|
maxPan.value = max
|
|
minPan.value = min
|
|
}
|
|
const sidebar = usePromoSidebar()
|
|
const loading_store = useLoading()
|
|
|
|
const camera = ref()
|
|
const cameraPosition = ref([1, 1, 1]) as unknown as Ref<Vector3>
|
|
|
|
const controlsState = reactive({
|
|
enableDamping: true,
|
|
maxPolarAngle: (60) * (Math.PI / 180),
|
|
minAzimuthAngle: (75) * (Math.PI / 180),
|
|
})
|
|
|
|
const raw_dataStore = useRawData()
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const sidebarScene = usePromoScene()
|
|
|
|
watch(() => route.params.target, sidebar.close)
|
|
const sidebarFunc = () => {
|
|
if (sidebar.is_open) {
|
|
sidebar.close()
|
|
} else {
|
|
sidebar.is_open = true
|
|
}
|
|
}
|
|
|
|
const prevClickableId = () => {
|
|
const item = sidebarScene.clickable.findIndex(el => el.id == sidebar.id_clickable)
|
|
if (item == 0) {
|
|
return sidebarScene.clickable[sidebarScene.clickable.length - 1].id
|
|
} else {
|
|
return sidebarScene.clickable[item - 1].id
|
|
}
|
|
}
|
|
const nextClickableId = () => {
|
|
const item = sidebarScene.clickable.findIndex(el => el.id == sidebar.id_clickable)
|
|
if (item == (sidebarScene.clickable.length - 1)) {
|
|
return sidebarScene.clickable[0].id
|
|
} else {
|
|
return sidebarScene.clickable[item + 1].id
|
|
}
|
|
}
|
|
</script>
|
|
<template>
|
|
<div>
|
|
<div v-if="raw_dataStore.data.loading"
|
|
style="position: absolute;z-index: 10;font-size: 6rem;text-align: center;top: 50%;left: 50%;transform: translate3d(-50%, -50%, 0);">
|
|
{{ loading_store.getStatus() }}
|
|
</div>
|
|
<div :class="[{ 'loading': raw_dataStore.data.loading }, 'canvas-wrapper']">
|
|
<TresCanvas window-size :alpha="false" power-preference="high-performance" :clear-color="PROMOBG"
|
|
:shadows="false">
|
|
<TresPerspectiveCamera :position="cameraPosition" ref="camera" />
|
|
<OrbitControls v-bind="controlsState" @change="onChange" make-default />
|
|
<!-- <Stats /> -->
|
|
<Suspense>
|
|
<LoadModels :source="route.params.target" :loaded_pan="loadedPan" :push="router.push" />
|
|
</Suspense>
|
|
</TresCanvas>
|
|
<div class="itemnav" v-if="sidebar.is_btn_open">
|
|
<div class="itemnav-close itemnav_one" v-if="sidebar.target">
|
|
<a href="#" @click.prevent="sidebar.closeBtn()">
|
|
<icon_plus />
|
|
</a>
|
|
</div>
|
|
<div class="itemnav-back">
|
|
<a href="#" @click.prevent="sidebar.open(prevClickableId())">
|
|
<icon_left />
|
|
</a>
|
|
</div>
|
|
<div class="itemnav-deep itemnav_big" v-if="sidebar.target">
|
|
<RouterLink :to="`/${route.params.item}/${sidebar.target}`">
|
|
<icon_enter />
|
|
</RouterLink>
|
|
</div>
|
|
<div class="itemnav-close itemnav_big" v-else>
|
|
<a href="#" @click.prevent="sidebar.closeBtn()">
|
|
<icon_plus />
|
|
</a>
|
|
</div>
|
|
<div class="itemnav-forward">
|
|
<a href="#" @click.prevent="sidebar.open(nextClickableId())">
|
|
<icon_right />
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="homelink" :class="[{ open: sidebar.is_open }]">
|
|
<a href="#" @click.prevent="sidebarFunc">
|
|
<i-icon-park-solid-left-c />
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<Sidebar />
|
|
</div>
|
|
</template>
|
|
<style scoped lang="scss">
|
|
.canvas-wrapper {
|
|
overflow: hidden;
|
|
height: 100vh;
|
|
width: 100vw;
|
|
position: absolute;
|
|
right: 0;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
}
|
|
|
|
.loading {
|
|
filter: blur(10px);
|
|
transition: all 300ms linear;
|
|
}
|
|
</style> |