dev #10
|
@ -120,6 +120,22 @@
|
||||||
"detail": "django.db",
|
"detail": "django.db",
|
||||||
"documentation": {}
|
"documentation": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "migrations",
|
||||||
|
"importPath": "django.db",
|
||||||
|
"description": "django.db",
|
||||||
|
"isExtraImport": true,
|
||||||
|
"detail": "django.db",
|
||||||
|
"documentation": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "models",
|
||||||
|
"importPath": "django.db",
|
||||||
|
"description": "django.db",
|
||||||
|
"isExtraImport": true,
|
||||||
|
"detail": "django.db",
|
||||||
|
"documentation": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "models",
|
"label": "models",
|
||||||
"importPath": "django.db",
|
"importPath": "django.db",
|
||||||
|
@ -1077,6 +1093,15 @@
|
||||||
"detail": "back.object.migrations.0004_alter_clickablearea_target_name",
|
"detail": "back.object.migrations.0004_alter_clickablearea_target_name",
|
||||||
"documentation": {}
|
"documentation": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Migration",
|
||||||
|
"kind": 6,
|
||||||
|
"importPath": "back.object.migrations.0005_scene3d_hdr_gainmap_scene3d_hdr_json_and_more",
|
||||||
|
"description": "back.object.migrations.0005_scene3d_hdr_gainmap_scene3d_hdr_json_and_more",
|
||||||
|
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('object', '0004_alter_clickablearea_target_name'),\n ]\n operations = [\n migrations.AddField(\n model_name='scene3d',\n name='hdr_gainmap',\n field=models.FileField(blank=True, null=True, upload_to=''),\n ),",
|
||||||
|
"detail": "back.object.migrations.0005_scene3d_hdr_gainmap_scene3d_hdr_json_and_more",
|
||||||
|
"documentation": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Scene3DAdmin",
|
"label": "Scene3DAdmin",
|
||||||
"kind": 6,
|
"kind": 6,
|
||||||
|
@ -1100,7 +1125,7 @@
|
||||||
"kind": 6,
|
"kind": 6,
|
||||||
"importPath": "back.object.models",
|
"importPath": "back.object.models",
|
||||||
"description": "back.object.models",
|
"description": "back.object.models",
|
||||||
"peekOfCode": "class Element3D(models.Model):\n parent = models.ForeignKey(\"self\", on_delete=models.PROTECT, blank=True, null=True)\n model_file = models.FileField(upload_to=group_based_upload_to)\n name = models.CharField(max_length=255)\n description = models.TextField()\n def __str__(self):\n return self.name\nclass Scene3D(models.Model):\n filter_horizontal = ('elements',)\n name = models.CharField(",
|
"peekOfCode": "class Element3D(models.Model):\n parent = models.ForeignKey(\"self\", on_delete=models.PROTECT, blank=True, null=True)\n model_file = models.FileField(upload_to=group_based_upload_to)\n name = models.CharField(max_length=255)\n description = models.TextField()\n def __str__(self):\n return self.name\nclass Scene3D(models.Model):\n filter_horizontal = (\"elements\",)\n name = models.CharField(",
|
||||||
"detail": "back.object.models",
|
"detail": "back.object.models",
|
||||||
"documentation": {}
|
"documentation": {}
|
||||||
},
|
},
|
||||||
|
@ -1109,7 +1134,7 @@
|
||||||
"kind": 6,
|
"kind": 6,
|
||||||
"importPath": "back.object.models",
|
"importPath": "back.object.models",
|
||||||
"description": "back.object.models",
|
"description": "back.object.models",
|
||||||
"peekOfCode": "class Scene3D(models.Model):\n filter_horizontal = ('elements',)\n name = models.CharField(\n max_length=120,\n )\n elements = models.ManyToManyField(Element3D)\n min_distance = models.IntegerField(\n validators=[MinValueValidator(1), MaxValueValidator(600)], blank=True, null=True\n )\n max_distance = models.IntegerField(",
|
"peekOfCode": "class Scene3D(models.Model):\n filter_horizontal = (\"elements\",)\n name = models.CharField(\n max_length=120,\n )\n elements = models.ManyToManyField(Element3D)\n min_distance = models.IntegerField(\n validators=[MinValueValidator(1), MaxValueValidator(600)], blank=True, null=True\n )\n max_distance = models.IntegerField(",
|
||||||
"detail": "back.object.models",
|
"detail": "back.object.models",
|
||||||
"documentation": {}
|
"documentation": {}
|
||||||
},
|
},
|
||||||
|
@ -1145,7 +1170,7 @@
|
||||||
"kind": 6,
|
"kind": 6,
|
||||||
"importPath": "back.object.serializers",
|
"importPath": "back.object.serializers",
|
||||||
"description": "back.object.serializers",
|
"description": "back.object.serializers",
|
||||||
"peekOfCode": "class Element3DSerializer(serializers.ModelSerializer):\n model_file = serializers.ImageField(use_url=False)\n class Meta:\n model = Element3D\n fields = \"__all__\"\nclass Scene3DSerializer(serializers.ModelSerializer):\n elements = Element3DSerializer(many=True)\n class Meta:\n model = Scene3D\n fields = \"__all__\"",
|
"peekOfCode": "class Element3DSerializer(serializers.ModelSerializer):\n model_file = serializers.ImageField(use_url=False)\n class Meta:\n model = Element3D\n fields = \"__all__\"\nclass Scene3DSerializer(serializers.ModelSerializer):\n elements = Element3DSerializer(many=True)\n hdr_gainmap = serializers.FileField(use_url=False)\n hdr_json = serializers.FileField(use_url=False)\n hdr_webp = serializers.FileField(use_url=False)",
|
||||||
"detail": "back.object.serializers",
|
"detail": "back.object.serializers",
|
||||||
"documentation": {}
|
"documentation": {}
|
||||||
},
|
},
|
||||||
|
@ -1154,7 +1179,7 @@
|
||||||
"kind": 6,
|
"kind": 6,
|
||||||
"importPath": "back.object.serializers",
|
"importPath": "back.object.serializers",
|
||||||
"description": "back.object.serializers",
|
"description": "back.object.serializers",
|
||||||
"peekOfCode": "class Scene3DSerializer(serializers.ModelSerializer):\n elements = Element3DSerializer(many=True)\n class Meta:\n model = Scene3D\n fields = \"__all__\"\n depth = 2\nclass ClickableAreaSerializer(serializers.ModelSerializer):\n class Meta:\n model = ClickableArea\n fields = \"__all__\"",
|
"peekOfCode": "class Scene3DSerializer(serializers.ModelSerializer):\n elements = Element3DSerializer(many=True)\n hdr_gainmap = serializers.FileField(use_url=False)\n hdr_json = serializers.FileField(use_url=False)\n hdr_webp = serializers.FileField(use_url=False)\n class Meta:\n model = Scene3D\n fields = \"__all__\"\n depth = 2\nclass ClickableAreaSerializer(serializers.ModelSerializer):",
|
||||||
"detail": "back.object.serializers",
|
"detail": "back.object.serializers",
|
||||||
"documentation": {}
|
"documentation": {}
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Element3D(models.Model):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Scene3D(models.Model):
|
class Scene3D(models.Model):
|
||||||
filter_horizontal = ('elements',)
|
filter_horizontal = ("elements",)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=120,
|
max_length=120,
|
||||||
)
|
)
|
||||||
|
@ -32,12 +32,22 @@ class Scene3D(models.Model):
|
||||||
validators=[MinValueValidator(1), MaxValueValidator(600)], blank=True, null=True
|
validators=[MinValueValidator(1), MaxValueValidator(600)], blank=True, null=True
|
||||||
)
|
)
|
||||||
max_distance = models.IntegerField(
|
max_distance = models.IntegerField(
|
||||||
validators=[MinValueValidator(2), MaxValueValidator(1000)], blank=True, null=True
|
validators=[MinValueValidator(2), MaxValueValidator(1000)],
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
|
<<<<<<< HEAD
|
||||||
gainmap = models.FileField(upload_to=group_based_upload_to)
|
gainmap = models.FileField(upload_to=group_based_upload_to)
|
||||||
json = models.FileField()
|
json = models.FileField()
|
||||||
webp = models.FileField()
|
webp = models.FileField()
|
||||||
|
=======
|
||||||
|
>>>>>>> 46d2586e693673bf1d8b8a390b297209bdf70ecb
|
||||||
|
|
||||||
|
hdr_gainmap = models.FileField(
|
||||||
|
upload_to=group_based_upload_to, blank=True, null=True
|
||||||
|
)
|
||||||
|
hdr_json = models.FileField(upload_to=group_based_upload_to, blank=True, null=True)
|
||||||
|
hdr_webp = models.FileField(upload_to=group_based_upload_to, blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
|
@ -11,8 +11,16 @@ class Element3DSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class Scene3DSerializer(serializers.ModelSerializer):
|
class Scene3DSerializer(serializers.ModelSerializer):
|
||||||
|
<<<<<<< HEAD
|
||||||
elements = serializers.ImageField(many=True, use_url=False)
|
elements = serializers.ImageField(many=True, use_url=False)
|
||||||
|
|
||||||
|
=======
|
||||||
|
elements = Element3DSerializer(many=True)
|
||||||
|
hdr_gainmap = serializers.FileField(use_url=False)
|
||||||
|
hdr_json = serializers.FileField(use_url=False)
|
||||||
|
hdr_webp = serializers.FileField(use_url=False)
|
||||||
|
|
||||||
|
>>>>>>> 46d2586e693673bf1d8b8a390b297209bdf70ecb
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Scene3D
|
model = Scene3D
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
|
@ -17,6 +17,7 @@ declare module 'vue' {
|
||||||
IMdiHexagonOutline: typeof import('~icons/mdi/hexagon-outline')['default']
|
IMdiHexagonOutline: typeof import('~icons/mdi/hexagon-outline')['default']
|
||||||
IMdiHome: typeof import('~icons/mdi/home')['default']
|
IMdiHome: typeof import('~icons/mdi/home')['default']
|
||||||
IMdiMonitorScreenshot: typeof import('~icons/mdi/monitor-screenshot')['default']
|
IMdiMonitorScreenshot: typeof import('~icons/mdi/monitor-screenshot')['default']
|
||||||
|
IMdiPagePreviousOutline: typeof import('~icons/mdi/page-previous-outline')['default']
|
||||||
IMdiShop: typeof import('~icons/mdi/shop')['default']
|
IMdiShop: typeof import('~icons/mdi/shop')['default']
|
||||||
IMdiVideo3d: typeof import('~icons/mdi/video3d')['default']
|
IMdiVideo3d: typeof import('~icons/mdi/video3d')['default']
|
||||||
Item: typeof import('./src/components/Floorplan/item.vue')['default']
|
Item: typeof import('./src/components/Floorplan/item.vue')['default']
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue';
|
import { onMounted, watch } from 'vue';
|
||||||
|
|
||||||
import { PMREMGenerator } from 'three';
|
import { PMREMGenerator } from 'three';
|
||||||
import { GainMapLoader } from '@monogrid/gainmap-js'
|
import { GainMapLoader } from '@monogrid/gainmap-js'
|
||||||
|
@ -9,14 +9,20 @@ import hdr_gainmap from '../../assets/promo/hdr/hdr-gainmap.webp'
|
||||||
import hdr_json from '../../assets/promo/hdr/hdr.json?url'
|
import hdr_json from '../../assets/promo/hdr/hdr.json?url'
|
||||||
import hdr_webp from '../../assets/promo/hdr/hdr.webp'
|
import hdr_webp from '../../assets/promo/hdr/hdr.webp'
|
||||||
|
|
||||||
const { renderer, scene } = useTresContext()
|
const props = defineProps(['hdr_webp', 'hdr_gainmap', 'hdr_json'])
|
||||||
|
|
||||||
onMounted(async () => {
|
const { renderer, scene } = useTresContext()
|
||||||
|
const loadEnv = async () => {
|
||||||
|
console.log(props)
|
||||||
const pmremGenerator = new PMREMGenerator(renderer.value);
|
const pmremGenerator = new PMREMGenerator(renderer.value);
|
||||||
pmremGenerator.compileEquirectangularShader();
|
pmremGenerator.compileEquirectangularShader();
|
||||||
|
|
||||||
const loader = new GainMapLoader(renderer.value)
|
const loader = new GainMapLoader(renderer.value)
|
||||||
const result = await loader.loadAsync([hdr_webp, hdr_gainmap, hdr_json,])
|
const result = await loader.loadAsync([
|
||||||
|
props.hdr_webp || hdr_webp,
|
||||||
|
props.hdr_gainmap || hdr_gainmap,
|
||||||
|
props.hdr_json || hdr_json,
|
||||||
|
])
|
||||||
|
|
||||||
const exrCubeRenderTarget = pmremGenerator.fromEquirectangular(result.renderTarget.texture);
|
const exrCubeRenderTarget = pmremGenerator.fromEquirectangular(result.renderTarget.texture);
|
||||||
const exrBackground = exrCubeRenderTarget.texture;
|
const exrBackground = exrCubeRenderTarget.texture;
|
||||||
|
@ -24,5 +30,9 @@ onMounted(async () => {
|
||||||
scene.value.environment = newEnvMap
|
scene.value.environment = newEnvMap
|
||||||
scene.value.background = exrBackground
|
scene.value.background = exrBackground
|
||||||
result.renderTarget.texture.dispose();
|
result.renderTarget.texture.dispose();
|
||||||
|
}
|
||||||
|
onMounted(async () => {
|
||||||
|
loadEnv()
|
||||||
})
|
})
|
||||||
|
watch(() => props.hdr_webp, loadEnv)
|
||||||
</script>
|
</script>
|
|
@ -1,11 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue';
|
import { reactive, ref, watch } from 'vue';
|
||||||
import { Box3, Color, Group, Mesh, MeshStandardMaterial, PointLight, SphereGeometry, Vector3 } from 'three';
|
import { Box3, Color, Group, Mesh, MeshStandardMaterial, PointLight, SphereGeometry, 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 Env from './env.vue'
|
||||||
|
|
||||||
import { IMAGE_URL, SERVER_URL, } from '../../constants'
|
import { IMAGE_URL, SERVER_URL, } from '../../constants'
|
||||||
import { usePromoSidebar } from '../../stores/promo_sidebar';
|
import { usePromoSidebar } from '../../stores/promo_sidebar';
|
||||||
|
import { usePromoScene } from '../../stores/promo_scene';
|
||||||
|
|
||||||
const props = defineProps(['source', 'loaded', 'loaded_pan'])
|
const props = defineProps(['source', 'loaded', 'loaded_pan'])
|
||||||
|
|
||||||
|
@ -22,12 +25,19 @@ const clickable = ref<clickableAreaType[]>([])
|
||||||
const clickable_objects = ref<any[]>([])
|
const clickable_objects = ref<any[]>([])
|
||||||
const clickable_items = ref<any[]>([])
|
const clickable_items = ref<any[]>([])
|
||||||
const sidebar = usePromoSidebar();
|
const sidebar = usePromoSidebar();
|
||||||
|
const sidebar_scene = usePromoScene()
|
||||||
const { controls, camera, scene } = useTresContext()
|
const { controls, camera, scene } = useTresContext()
|
||||||
const { seekByName } = useSeek()
|
const { seekByName } = useSeek()
|
||||||
|
const envVars = reactive({}) as { hdr_gainmap?: string, hdr_json?: string, hdr_webp?: string }
|
||||||
|
|
||||||
const loadModels = async () => {
|
const loadModels = async () => {
|
||||||
const res = await fetch(`${SERVER_URL}/api/obj/scene/${props.source}`)
|
const res = await fetch(`${SERVER_URL}/api/obj/scene/${props.source}`)
|
||||||
const raw_data = await res.json() as scene3D
|
const raw_data = await res.json() as scene3D
|
||||||
|
|
||||||
|
if (raw_data.hdr_gainmap) envVars.hdr_gainmap = `${IMAGE_URL}/${raw_data.hdr_gainmap}`
|
||||||
|
if (raw_data.hdr_json) envVars.hdr_json = `${IMAGE_URL}/${raw_data.hdr_json}`
|
||||||
|
if (raw_data.hdr_webp) envVars.hdr_webp = `${IMAGE_URL}/${raw_data.hdr_webp}`
|
||||||
|
|
||||||
const data = raw_data.elements
|
const data = raw_data.elements
|
||||||
if (!controls.value) return;
|
if (!controls.value) return;
|
||||||
|
|
||||||
|
@ -39,8 +49,10 @@ const loadModels = async () => {
|
||||||
camera.value?.position.set(1, 1, 1);
|
camera.value?.position.set(1, 1, 1);
|
||||||
camera.value?.lookAt(new Vector3(1, 1, 1));
|
camera.value?.lookAt(new Vector3(1, 1, 1));
|
||||||
|
|
||||||
|
const sidebar_items = []
|
||||||
for (let index = 0; index < data.length; index++) {
|
for (let index = 0; index < data.length; index++) {
|
||||||
const element = data[index];
|
const element = data[index];
|
||||||
|
sidebar_items.push({ ...element, is_enabled: true })
|
||||||
const item = {} as model3DType
|
const item = {} as model3DType
|
||||||
|
|
||||||
item.modelUrl = `${IMAGE_URL}/${element.model_file}`
|
item.modelUrl = `${IMAGE_URL}/${element.model_file}`
|
||||||
|
@ -55,6 +67,8 @@ const loadModels = async () => {
|
||||||
const clickable_areas = await res.json()
|
const clickable_areas = await res.json()
|
||||||
clickable.value.push(...clickable_areas)
|
clickable.value.push(...clickable_areas)
|
||||||
}
|
}
|
||||||
|
sidebar_scene.setData(sidebar_items)
|
||||||
|
sidebar.open()
|
||||||
|
|
||||||
for (let index = 0; index < clickable.value.length; index++) {
|
for (let index = 0; index < clickable.value.length; index++) {
|
||||||
const element = clickable.value[index];
|
const element = clickable.value[index];
|
||||||
|
@ -140,6 +154,9 @@ watch(() => props.source, () => {
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
<Suspense>
|
||||||
|
<Env v-bind="envVars" />
|
||||||
|
</Suspense>
|
||||||
<TresGroup name="loaded">
|
<TresGroup name="loaded">
|
||||||
<template v-for="item in models">
|
<template v-for="item in models">
|
||||||
<TresGroup :name="item.name">
|
<TresGroup :name="item.name">
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { Vector3 } from 'three';
|
||||||
import { TresCanvas } from '@tresjs/core';
|
import { TresCanvas } from '@tresjs/core';
|
||||||
import { StatsGl, OrbitControls } from '@tresjs/cientos'
|
import { StatsGl, OrbitControls } from '@tresjs/cientos'
|
||||||
|
|
||||||
import Env from './env.vue'
|
|
||||||
import LoadModels from './load_models.vue'
|
import LoadModels from './load_models.vue'
|
||||||
import Sidebar from './sidebar.vue'
|
import Sidebar from './sidebar.vue'
|
||||||
import { usePromoSidebar } from '../../stores/promo_sidebar';
|
import { usePromoSidebar } from '../../stores/promo_sidebar';
|
||||||
|
@ -62,9 +61,6 @@ watch(() => route.params.target, () => {
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<TresPerspectiveCamera :position="cameraPosition" ref="camera" />
|
<TresPerspectiveCamera :position="cameraPosition" ref="camera" />
|
||||||
<OrbitControls v-bind="controlsState" @change="onChange" make-default />
|
<OrbitControls v-bind="controlsState" @change="onChange" make-default />
|
||||||
<Suspense>
|
|
||||||
<Env />
|
|
||||||
</Suspense>
|
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<LoadModels :source="source" :loaded="set_model_load_status" :loaded_pan="loadedPan" />
|
<LoadModels :source="source" :loaded="set_model_load_status" :loaded_pan="loadedPan" />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
@ -73,10 +69,15 @@ watch(() => route.params.target, () => {
|
||||||
<TresShadowMaterial :opacity="0.2" />
|
<TresShadowMaterial :opacity="0.2" />
|
||||||
</TresMesh>
|
</TresMesh>
|
||||||
</TresCanvas>
|
</TresCanvas>
|
||||||
<RouterLink to="/promo/main/" class="homelink">
|
<div class="homelink">
|
||||||
|
<a href="#" @click.prevent="sidebar.open" v-if="!sidebar.is_open">
|
||||||
|
<i-mdi-page-previous-outline />
|
||||||
|
</a>
|
||||||
|
<RouterLink to="/promo/main/">
|
||||||
<i-mdi-home />
|
<i-mdi-home />
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -96,18 +97,25 @@ watch(() => route.params.target, () => {
|
||||||
filter: blur(10px);
|
filter: blur(10px);
|
||||||
transition: all 300ms linear;
|
transition: all 300ms linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.homelink {
|
.homelink {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
font-size: 3rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin-bottom: 2rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 1px solid white;
|
border: 1px solid white;
|
||||||
background: white;
|
background: white;
|
||||||
padding: 0.5rem;
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
svg {
|
display: block;
|
||||||
font-size: 5rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -3,10 +3,12 @@ import { ref } from 'vue';
|
||||||
import { RouterLink } from 'vue-router';
|
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';
|
||||||
|
import { usePromoScene } from '../../stores/promo_scene';
|
||||||
|
|
||||||
const sidebar = usePromoSidebar()
|
const sidebar = usePromoSidebar()
|
||||||
|
const scene = usePromoScene()
|
||||||
const sidebar_obj = ref()
|
const sidebar_obj = ref()
|
||||||
|
console.log(scene.list)
|
||||||
// onClickOutside(sidebar_obj, () => sidebar.close())
|
// onClickOutside(sidebar_obj, () => sidebar.close())
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
@ -14,7 +16,9 @@ const sidebar_obj = ref()
|
||||||
<a href="#" @click.prevent="sidebar.close" class="sidebar-close">
|
<a href="#" @click.prevent="sidebar.close" class="sidebar-close">
|
||||||
<i-mdi-close />
|
<i-mdi-close />
|
||||||
</a>
|
</a>
|
||||||
<template v-if="sidebar.is_open">
|
<div class="sidebar-content">
|
||||||
|
<template v-if="!sidebar.is_open"></template>
|
||||||
|
<template v-else-if="(sidebar.description && sidebar.title)">
|
||||||
<h2>{{ sidebar.title }}</h2>
|
<h2>{{ sidebar.title }}</h2>
|
||||||
<template v-for="p in sidebar.description.split('\n')">
|
<template v-for="p in sidebar.description.split('\n')">
|
||||||
<p>{{ p }}</p>
|
<p>{{ p }}</p>
|
||||||
|
@ -22,8 +26,14 @@ const sidebar_obj = ref()
|
||||||
<RouterLink class="btn" :to="`/promo/main/${sidebar.target}`" v-if="sidebar.target">
|
<RouterLink class="btn" :to="`/promo/main/${sidebar.target}`" v-if="sidebar.target">
|
||||||
{{ sidebar.target_name }}
|
{{ sidebar.target_name }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<template v-for="item in scene.list">
|
||||||
|
<h3>{{ item.name }}</h3>
|
||||||
|
<p>{{ item.description }}</p>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@ -35,8 +45,9 @@ const sidebar_obj = ref()
|
||||||
right: -27vw;
|
right: -27vw;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transition: all 300ms linear;
|
transition: all 300ms linear;
|
||||||
|
line-height: 1.25;
|
||||||
|
|
||||||
padding: 2rem;
|
padding: 3rem 2rem 2rem;
|
||||||
|
|
||||||
&.open {
|
&.open {
|
||||||
right: 0
|
right: 0
|
||||||
|
@ -50,17 +61,31 @@ const sidebar_obj = ref()
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
margin: 1rem
|
margin: 1rem
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p,
|
||||||
|
h3 {
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
|
@ -14,6 +14,9 @@ interface scene3D {
|
||||||
name: string
|
name: string
|
||||||
min_distance: number
|
min_distance: number
|
||||||
max_distance: number
|
max_distance: number
|
||||||
|
hdr_gainmap?: string
|
||||||
|
hdr_json?: string
|
||||||
|
hdr_webp?: string
|
||||||
elements: element3DType[]
|
elements: element3DType[]
|
||||||
}
|
}
|
||||||
interface element3DType {
|
interface element3DType {
|
||||||
|
@ -40,8 +43,8 @@ interface clickableAreaType {
|
||||||
target_name?: string
|
target_name?: string
|
||||||
}
|
}
|
||||||
interface PromoSidebarData {
|
interface PromoSidebarData {
|
||||||
title: string
|
title?: string
|
||||||
description: string
|
description?: string
|
||||||
target?: string
|
target?: string
|
||||||
target_name?: string
|
target_name?: string
|
||||||
}
|
}
|
||||||
|
@ -49,3 +52,11 @@ interface PromoSidebar extends PromoSidebarData {
|
||||||
loading: boolean
|
loading: boolean
|
||||||
is_open: boolean
|
is_open: boolean
|
||||||
}
|
}
|
||||||
|
interface PromoScene {
|
||||||
|
id: number
|
||||||
|
model_file: string
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
parent?: number
|
||||||
|
is_enabled: boolean
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const usePromoScene = defineStore('promo_scene', {
|
||||||
|
state: () => {
|
||||||
|
return { list: [] as PromoScene[] }
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setData(data: PromoScene[]) {
|
||||||
|
this.list = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -3,10 +3,10 @@ import { defineStore } from 'pinia'
|
||||||
export const usePromoSidebar = defineStore('promo_sidebar', {
|
export const usePromoSidebar = defineStore('promo_sidebar', {
|
||||||
state: () => {
|
state: () => {
|
||||||
return {
|
return {
|
||||||
title: 'Сайдбар',
|
title: undefined,
|
||||||
description: 'Описание',
|
description: undefined,
|
||||||
target: undefined,
|
target: undefined,
|
||||||
target_name: 'Перейти дальше',
|
target_name: undefined,
|
||||||
loading: true,
|
loading: true,
|
||||||
is_open: false
|
is_open: false
|
||||||
} as PromoSidebar
|
} as PromoSidebar
|
||||||
|
|
Loading…
Reference in New Issue