bx-1379-redesign #15
|
@ -10,7 +10,7 @@ declare module 'vue' {
|
|||
Composer: typeof import('./src/components/Promo/composer.vue')['default']
|
||||
Env: typeof import('./src/components/Promo/env.vue')['default']
|
||||
Floorplan: typeof import('./src/components/Floorplan/index.vue')['default']
|
||||
Gallery: typeof import('./src/components/Promo/gallery.vue')['default']
|
||||
Gallery: typeof import('./src/components/Gallery/index.vue')['default']
|
||||
Game: typeof import('./src/components/Game.vue')['default']
|
||||
Home: typeof import('./src/components/Home.vue')['default']
|
||||
IIconMdiHomeOutline: typeof import('~icons/ic/on-mdi-home-outline')['default']
|
||||
|
@ -33,6 +33,7 @@ declare module 'vue' {
|
|||
IMdiShop: typeof import('~icons/mdi/shop')['default']
|
||||
IMdiVideo3d: typeof import('~icons/mdi/video3d')['default']
|
||||
Item: typeof import('./src/components/Floorplan/item.vue')['default']
|
||||
Load: typeof import('./src/components/load.vue')['default']
|
||||
Load_models: typeof import('./src/components/Promo/load_models.vue')['default']
|
||||
Main: typeof import('./src/components/Promo/main.vue')['default']
|
||||
ModelItem: typeof import('./src/components/Promo/modelItem.vue')['default']
|
||||
|
@ -45,6 +46,6 @@ declare module 'vue' {
|
|||
RandomIcon: typeof import('./src/components/RandomIcon.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Sidebar: typeof import('./src/components/Promo/sidebar.vue')['default']
|
||||
Sidebar: typeof import('./src/components/sidebar.vue')['default']
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
<template>
|
||||
<Suspense>
|
||||
<Load />
|
||||
</Suspense>
|
||||
<Suspense>
|
||||
<RouterView />
|
||||
</Suspense>
|
||||
<Nav />
|
||||
<Suspense>
|
||||
<Nav />
|
||||
</Suspense>
|
||||
</template>
|
|
@ -0,0 +1,126 @@
|
|||
<script setup lang="ts">
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import GalleryItem from './gallery.vue';
|
||||
import KLogo from "../../assets/promo/logo.svg";
|
||||
import { useItem } from "../../stores/item";
|
||||
|
||||
const router = useRouter()
|
||||
const page = useItem()
|
||||
|
||||
const startColor = `hsl(${(Math.random() * 360).toFixed()}, 100%, 50%)`
|
||||
const endColor = `hsl(${(Math.random() * 360).toFixed()}, 100%, 50%)`
|
||||
</script>
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="pin" @click="router.push(`/${page.slug}/${page.scene_3d}`)">
|
||||
<KLogo />
|
||||
</div>
|
||||
<GalleryItem :files="page.images" v-if="page.images && page.images.length" />
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
* {
|
||||
--logo-start-color: v-bind(startColor);
|
||||
--logo-end-color: v-bind(endColor);
|
||||
--anim-time: 4s;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
background-image: url(../../assets/promo/map.png);
|
||||
background-position: 50% 100%;
|
||||
background-size: auto 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pin {
|
||||
cursor: pointer;
|
||||
|
||||
border-radius: 0.25rem;
|
||||
overflow: hidden;
|
||||
|
||||
position: absolute;
|
||||
bottom: 20vh;
|
||||
left: calc(50% - 1vw);
|
||||
|
||||
color: white;
|
||||
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 0.25rem;
|
||||
|
||||
animation: bounce2 var(--anim-time) ease infinite;
|
||||
transition: all 300ms linear;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1rem;
|
||||
right: -1rem;
|
||||
bottom: -1rem;
|
||||
left: -1rem;
|
||||
background-image: linear-gradient(var(--logo-start-color), var(--logo-end-color));
|
||||
animation: bounce2grad var(--anim-time) ease infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
svg {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
color: #fff;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
// animation-play-state: paused;
|
||||
animation: none;
|
||||
transform: scale(1.5);
|
||||
|
||||
&::before {
|
||||
// animation-play-state: paused;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@keyframes bounce2grad {
|
||||
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: rotate(90deg)
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: rotate(20deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce2 {
|
||||
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(0) scale(1.5);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateY(-2rem);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translateY(-1rem);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,128 +1,115 @@
|
|||
<script setup lang="ts">
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import type { Ref } from 'vue'
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import KLogo from "../../assets/promo/logo.svg";
|
||||
import { useItem } from "../../stores/item";
|
||||
import { Vector3 } from 'three';
|
||||
import { TresCanvas } from '@tresjs/core';
|
||||
import { OrbitControls, Stats } from '@tresjs/cientos'
|
||||
import '@tresjs/leches/styles'
|
||||
|
||||
const router = useRouter()
|
||||
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 { useItem } from '../../stores/item';
|
||||
import { useRawData } from '../../stores/raw_data';
|
||||
|
||||
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: (Math.PI / 2) - 0.07,
|
||||
minAzimuthAngle: (Math.PI / 2) - 0.20,
|
||||
})
|
||||
|
||||
const raw_data = useRawData()
|
||||
const route = useRoute()
|
||||
const page = useItem()
|
||||
|
||||
const startColor = `hsl(${(Math.random() * 360).toFixed()}, 100%, 50%)`
|
||||
const endColor = `hsl(${(Math.random() * 360).toFixed()}, 100%, 50%)`
|
||||
const source = ref(route.params.target)
|
||||
watch(() => route.params.target, () => {
|
||||
let t = '1'
|
||||
if (route.params.target) t = route.params.target as string
|
||||
if (source.value !== t) {
|
||||
source.value = t
|
||||
sidebar.close()
|
||||
}
|
||||
},)
|
||||
|
||||
await page.load(route.params)
|
||||
const sidebarFunc = () => {
|
||||
if (sidebar.is_open) {
|
||||
sidebar.close()
|
||||
} else {
|
||||
sidebar.open()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const page = useItem();
|
||||
if (!page.slug) {
|
||||
page.load(route.params)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="pin" @click="router.push(`/${page.slug}/${page.scene_3d}`)">
|
||||
<KLogo />
|
||||
<div>
|
||||
<div v-if="raw_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>
|
||||
<Gallery :files="page.images" />
|
||||
<div :class="[{ 'loading': raw_data.loading }, 'canvas-wrapper']">
|
||||
<TresCanvas window-size :alpha="false" power-preference="high-performance" :clear-color="PROMOBG"
|
||||
:shadows="false">
|
||||
<Stats />
|
||||
<TresPerspectiveCamera :position="cameraPosition" ref="camera" />
|
||||
<OrbitControls v-bind="controlsState" @change="onChange" make-default />
|
||||
<Suspense>
|
||||
<LoadModels :source="source" :loaded_pan="loadedPan" :key="source as string" />
|
||||
</Suspense>
|
||||
</TresCanvas>
|
||||
<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">
|
||||
* {
|
||||
--logo-start-color: v-bind(startColor);
|
||||
--logo-end-color: v-bind(endColor);
|
||||
--anim-time: 4s;
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100vw;
|
||||
.canvas-wrapper {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
|
||||
background-image: url(../../assets/promo/map.png);
|
||||
background-position: 50% 100%;
|
||||
background-size: auto 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pin {
|
||||
cursor: pointer;
|
||||
|
||||
border-radius: 0.25rem;
|
||||
overflow: hidden;
|
||||
|
||||
width: 100vw;
|
||||
position: absolute;
|
||||
bottom: 20vh;
|
||||
left: calc(50% - 1vw);
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
color: white;
|
||||
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
padding: 0.25rem;
|
||||
|
||||
animation: bounce2 var(--anim-time) ease infinite;
|
||||
.loading {
|
||||
filter: blur(10px);
|
||||
transition: all 300ms linear;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1rem;
|
||||
right: -1rem;
|
||||
bottom: -1rem;
|
||||
left: -1rem;
|
||||
background-image: linear-gradient(var(--logo-start-color), var(--logo-end-color));
|
||||
animation: bounce2grad var(--anim-time) ease infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
svg {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
color: #fff;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
// animation-play-state: paused;
|
||||
animation: none;
|
||||
transform: scale(1.5);
|
||||
|
||||
&::before {
|
||||
// animation-play-state: paused;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@keyframes bounce2grad {
|
||||
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: rotate(90deg)
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: rotate(60deg);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: rotate(20deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce2 {
|
||||
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(0) scale(1.5);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateY(-2rem);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translateY(-1rem);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,115 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import type { Ref } from 'vue'
|
||||
import { useRoute } 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 { useItem } from '../../stores/item';
|
||||
import { useRawData } from '../../stores/raw_data';
|
||||
|
||||
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: (Math.PI / 2) - 0.07,
|
||||
minAzimuthAngle: (Math.PI / 2) - 0.20,
|
||||
})
|
||||
|
||||
const raw_data = useRawData()
|
||||
const route = useRoute()
|
||||
|
||||
const source = ref(route.params.target)
|
||||
watch(() => route.params.target, () => {
|
||||
let t = '1'
|
||||
if (route.params.target) t = route.params.target as string
|
||||
if (source.value !== t) {
|
||||
source.value = t
|
||||
sidebar.close()
|
||||
}
|
||||
},)
|
||||
|
||||
const sidebarFunc = () => {
|
||||
if (sidebar.is_open) {
|
||||
sidebar.close()
|
||||
} else {
|
||||
sidebar.open()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const page = useItem();
|
||||
if (!page.slug) {
|
||||
page.load(route.params)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="raw_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_data.loading }, 'canvas-wrapper']">
|
||||
<TresCanvas window-size :alpha="false" power-preference="high-performance" :clear-color="PROMOBG"
|
||||
:shadows="false">
|
||||
<Stats />
|
||||
<TresPerspectiveCamera :position="cameraPosition" ref="camera" />
|
||||
<OrbitControls v-bind="controlsState" @change="onChange" make-default />
|
||||
<Suspense>
|
||||
<LoadModels :source="source" :loaded_pan="loadedPan" :key="source as string" />
|
||||
</Suspense>
|
||||
</TresCanvas>
|
||||
<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>
|
|
@ -0,0 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useItem } from '../stores/item';
|
||||
|
||||
const page = useItem()
|
||||
const route = useRoute()
|
||||
|
||||
await page.load(route.params)
|
||||
</script>
|
||||
<template>
|
||||
{{ route.params }}
|
||||
</template>
|
|
@ -1,8 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { RouterLink, useRoute } from 'vue-router';
|
||||
import { usePromoSidebar } from '../../stores/promo_sidebar';
|
||||
import { usePromoScene } from '../../stores/promo_scene';
|
||||
import { usePromoSidebar } from '../stores/promo_sidebar';
|
||||
import { usePromoScene } from '../stores/promo_scene';
|
||||
|
||||
const sidebar = usePromoSidebar()
|
||||
const sidebar_scene = usePromoScene()
|
|
@ -15,6 +15,7 @@ interface scene3D {
|
|||
min_distance: number
|
||||
max_distance: number
|
||||
elements: element3DType[]
|
||||
descrition?: string
|
||||
env: {
|
||||
hdr_gainmap?: string
|
||||
hdr_json?: string
|
||||
|
|
|
@ -5,13 +5,13 @@ import { createWebHistory, createRouter } from 'vue-router'
|
|||
import './assets/main.scss'
|
||||
|
||||
import App from './App.vue'
|
||||
import Gallery from './components/Gallery/index.vue'
|
||||
import Promo from './components/Promo/index.vue'
|
||||
import PromoMain from './components/Promo/main.vue'
|
||||
|
||||
const routes = [
|
||||
{ path: '/', component: Promo, name: 'home_no' },
|
||||
{ path: '/:item/gallery', component: Promo, name: 'gallery' },
|
||||
{ path: '/:item/:target', component: PromoMain, name: 'scene' },
|
||||
{ path: '/', component: Gallery, name: 'home_no' },
|
||||
{ path: '/:item/gallery', component: Gallery, name: 'gallery' },
|
||||
{ path: '/:item/:target', component: Promo, name: 'scene' },
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
|
Loading…
Reference in New Issue