bx-1379-redesign #15

Merged
ksenia_mikhailova merged 124 commits from bx-1379-redesign into dev 2024-09-06 15:39:13 +03:00
10 changed files with 251 additions and 234 deletions
Showing only changes of commit 8f037eb84e - Show all commits

View File

@ -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']
}
}

View File

@ -1,6 +1,11 @@
<template>
<Suspense>
<Load />
</Suspense>
<Suspense>
<RouterView />
</Suspense>
<Nav />
<Suspense>
<Nav />
</Suspense>
</template>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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()

View File

@ -15,6 +15,7 @@ interface scene3D {
min_distance: number
max_distance: number
elements: element3DType[]
descrition?: string
env: {
hdr_gainmap?: string
hdr_json?: string

View File

@ -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({