89 lines
2.3 KiB
Vue
89 lines
2.3 KiB
Vue
<script setup lang="ts">
|
|
import { Vector3 } from "three";
|
|
|
|
const { openModal } = useModalState();
|
|
|
|
const types = {
|
|
bench: defineAsyncComponent(() => import("./bench.vue")),
|
|
table: defineAsyncComponent(() => import("./bench-table.vue")),
|
|
};
|
|
|
|
const props = defineProps({
|
|
type: {
|
|
type: String as PropType<keyof typeof types>,
|
|
default: "bench",
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const camera = ref();
|
|
const controls = ref();
|
|
|
|
const controlsState = reactive({
|
|
minDistance: 0.5,
|
|
maxDistance: 5,
|
|
enablePan: false,
|
|
enableZoom: false,
|
|
// maxPolarAngle: Math.PI / 2 - 0.2
|
|
});
|
|
|
|
const changeDistance = (v = 1) => {
|
|
if (camera.value && controls.value) {
|
|
const distance = camera.value.position.distanceTo(new Vector3(0, 0, 0));
|
|
const r = distance + v;
|
|
camera.value.position.normalize().multiplyScalar(r);
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="relative h-[600px] max-h-screen">
|
|
<ClientOnly fallback-tag="div">
|
|
<template #fallback>
|
|
<div class="fallback">Загрузка 3D модели</div>
|
|
</template>
|
|
<TresCanvas height="600" clear-color="#e2e8f0">
|
|
<TresPerspectiveCamera :position="new Vector3(-7, 2, 4)" ref="camera" />
|
|
<OrbitControls v-bind="controlsState" ref="controls" make-default />
|
|
<ModelEnv />
|
|
<Suspense>
|
|
<component :is="types[props.type]" />
|
|
</Suspense>
|
|
</TresCanvas>
|
|
<div class="canvas-icons top-4 left-4">
|
|
<a
|
|
href="#"
|
|
@click.prevent="changeDistance(-0.5)"
|
|
:class="[
|
|
{
|
|
disabled: camera
|
|
? camera.position.distanceTo(new Vector3(0, 0, 0)) <=
|
|
controlsState.minDistance
|
|
: null,
|
|
},
|
|
]"
|
|
>
|
|
<Icon name="mdi:plus-circle-outline" />
|
|
</a>
|
|
<a
|
|
href="#"
|
|
@click.prevent="changeDistance(0.5)"
|
|
:class="[
|
|
{
|
|
disabled: camera
|
|
? camera.position.distanceTo(new Vector3(0, 0, 0)) >=
|
|
controlsState.maxDistance
|
|
: null,
|
|
},
|
|
]"
|
|
>
|
|
<Icon name="mdi:minus-circle-outline" />
|
|
</a>
|
|
</div>
|
|
</ClientOnly>
|
|
<div class="absolute bottom-4 left-1/2 -translate-x-1/2">
|
|
<button @click.prevent="openModal">Заказать</button>
|
|
</div>
|
|
</div>
|
|
</template>
|