bx-865-apps #1

Merged
ksenia_mikhailova merged 140 commits from bx-865-apps into main 2024-06-27 15:03:27 +03:00
6 changed files with 45 additions and 21 deletions
Showing only changes of commit 6a6ae29900 - Show all commits

View File

@ -1,12 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { IMAGE_URL, SERVER_URL, } from '../../constants' import { onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { Box3, Vector2, Vector3 } from 'three'; import { Box3, Vector2, Vector3 } from 'three';
import { useTresContext, useSeek } from '@tresjs/core'; import { useTresContext, useSeek } from '@tresjs/core';
import { useGLTF } from '@tresjs/cientos' import { useGLTF } from '@tresjs/cientos'
import { IMAGE_URL, SERVER_URL, } from '../../constants'
import { usePromoSidebar } from '../../stores/promo_sidebar'; import { usePromoSidebar } from '../../stores/promo_sidebar';
const props = defineProps(['source'])
const max_size = reactive({ const max_size = reactive({
x: 0, y: 0, z: 0 x: 0, y: 0, z: 0
}) })
@ -22,13 +24,17 @@ function shadows_and_pos(scene: any) {
const models = ref<model3DType[]>([]) const models = ref<model3DType[]>([])
const clickable = ref<clickableAreaType[]>([]) const clickable = ref<clickableAreaType[]>([])
const clickable_objects = ref<any[]>([]) const clickable_objects = ref<any[]>([])
const { controls, raycaster, camera, scene } = useTresContext() const { controls, raycaster, camera, scene, renderer } = useTresContext()
const { seekByName } = useSeek() const { seekByName } = useSeek()
const sidebar = usePromoSidebar() const sidebar = usePromoSidebar()
const loadModels = async () => { const loadModels = async () => {
const res = await fetch(`${SERVER_URL}/api/obj/element/?parent__isnull=True`) const res = await fetch(`${SERVER_URL}/api/obj/element/${props.source}`)
const data = await res.json() as element3DType[] const raw_data = await res.json() as element3DType[] | element3DType
let data = raw_data as element3DType[]
if (props.source.endsWith('/')) {
data = [raw_data] as element3DType[]
}
if (!controls.value) return if (!controls.value) return
const c = (controls.value as any) const c = (controls.value as any)
const distance = { const distance = {
@ -107,9 +113,16 @@ const clickEvent = (event: MouseEvent) => {
} }
console.timeEnd('raycaster') console.timeEnd('raycaster')
} }
watch(() => props.source, () => {
const loaded = seekByName(scene.value, 'loaded')
if (loaded) {
scene.value.remove(loaded)
}
loadModels()
})
</script> </script>
<template> <template>
<TresGroup v-for="item in models"> <TresGroup v-for="item in models" name="loaded">
<TresObject3D v-bind="item.modelFile.clone()" /> <TresObject3D v-bind="item.modelFile.clone()" />
</TresGroup> </TresGroup>
</template> </template>

View File

@ -1,8 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue'; import { reactive, ref, watch } from 'vue';
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { Vector3 } from 'three'; import { useRoute, useRouter } from 'vue-router';
import { Vector3 } from 'three';
import { TresCanvas } from '@tresjs/core'; import { TresCanvas } from '@tresjs/core';
import { CameraControls, useProgress, StatsGl } from '@tresjs/cientos' import { CameraControls, useProgress, StatsGl } from '@tresjs/cientos'
@ -34,6 +35,15 @@ const point_light = reactive({
position: new Vector3(-100, 50, 5), position: new Vector3(-100, 50, 5),
}) })
const route = useRoute()
const source = ref(route.params.target ? (route.params.target.toString() + '/') : '?parent__isnull=True')
watch(() => route.params.target, () => {
let t = '?parent__isnull=True'
if (route.params.target) t = route.params.target.toString() + '/'
if (source.value !== t) {
source.value = t
}
}, { deep: true })
</script> </script>
<template> <template>
<div> <div>
@ -51,7 +61,7 @@ const point_light = reactive({
<Env /> <Env />
</Suspense> </Suspense>
<Suspense> <Suspense>
<LoadModels /> <LoadModels :source="source" />
</Suspense> </Suspense>
<TresMesh cast-shadow> <TresMesh cast-shadow>
<TresBoxGeometry :args="[1, 1, 1]" /> <TresBoxGeometry :args="[1, 1, 1]" />
@ -64,7 +74,7 @@ const point_light = reactive({
<TresPointLight v-bind="point_light" cast-shadow /> <TresPointLight v-bind="point_light" cast-shadow />
</TresCanvas> </TresCanvas>
</div> </div>
<Sidebar/> <Sidebar />
</div> </div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
@ -79,5 +89,4 @@ const point_light = reactive({
font-size: 2rem; font-size: 2rem;
min-height: 100vh; min-height: 100vh;
} }
</style> </style>

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import { RouterLink } from 'vue-router';
import { onClickOutside } from '@vueuse/core' import { onClickOutside } from '@vueuse/core'
import { usePromoSidebar } from '../../stores/promo_sidebar'; import { usePromoSidebar } from '../../stores/promo_sidebar';
@ -18,6 +19,9 @@ onClickOutside(sidebar_obj, () => sidebar.close())
<template v-for="p in sidebar.description.split('\n')"> <template v-for="p in sidebar.description.split('\n')">
<p>{{ p }}</p> <p>{{ p }}</p>
</template> </template>
<RouterLink :to="`/promo/main/${sidebar.target}`" v-if="sidebar.target">
Перейти на темную сторону
</RouterLink>
</template> </template>
</div> </div>
</template> </template>

10
front/src/index.d.ts vendored
View File

@ -31,14 +31,12 @@ interface clickableAreaType {
source: number; source: number;
target: number; target: number;
} }
interface PromoSidebar {
title: string
description: string
loading: boolean
is_open: boolean
}
interface PromoSidebarData { interface PromoSidebarData {
title: string title: string
description: string description: string
target?: string target?: string
} }
interface PromoSidebar extends PromoSidebarData {
loading: boolean
is_open: boolean
}

View File

@ -22,6 +22,7 @@ const routes = [
{ path: '/floorplan/:id', component: FloorplanItem }, { path: '/floorplan/:id', component: FloorplanItem },
{ path: '/promo', component: Promo }, { path: '/promo', component: Promo },
{ path: '/promo/:page', component: PromoMain }, { path: '/promo/:page', component: PromoMain },
{ path: '/promo/:page/:target', component: PromoMain },
{ path: '/promo/:page/item/:name', component: PromoItem }, { path: '/promo/:page/item/:name', component: PromoItem },
] ]

View File

@ -5,6 +5,7 @@ export const usePromoSidebar = defineStore('promo_sidebar', {
return { return {
title: 'Сайдбар', title: 'Сайдбар',
description: 'Описание', description: 'Описание',
target: undefined,
loading: true, loading: true,
is_open: false is_open: false
} as PromoSidebar } as PromoSidebar
@ -15,9 +16,7 @@ export const usePromoSidebar = defineStore('promo_sidebar', {
this.loading = true this.loading = true
}, },
setData(data: PromoSidebarData) { setData(data: PromoSidebarData) {
const { title, description } = data this.$state = Object.assign(this.$state, data)
this.title = title
this.description = description
}, },
close() { close() {
this.$reset() this.$reset()