dev #84
|
@ -348,11 +348,6 @@ button {
|
||||||
|
|
||||||
&_color {
|
&_color {
|
||||||
@apply w-full;
|
@apply w-full;
|
||||||
|
|
||||||
.color_picker,
|
|
||||||
.list_picker {
|
|
||||||
// @apply ml-4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=range] {
|
input[type=range] {
|
||||||
|
@ -361,35 +356,15 @@ button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.color_picker {
|
.picker {
|
||||||
@apply leading-none;
|
@apply leading-none;
|
||||||
|
|
||||||
&-selected {
|
&-selected {
|
||||||
@apply size-10 rounded border-gray-300 shadow inline-block leading-none;
|
@apply size-10 rounded border-gray-300 shadow inline-block leading-none;
|
||||||
|
|
||||||
&__active {
|
|
||||||
@apply outline outline-2 outline-offset-2 outline-primary;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-changer {
|
&-changer {
|
||||||
@apply absolute w-80 z-20 p-4 border rounded bg-white flex gap-0 right-0;
|
@apply flex gap-0;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list_picker {
|
|
||||||
@apply leading-none;
|
|
||||||
|
|
||||||
&-selected {
|
|
||||||
@apply size-10 rounded border-gray-300 shadow inline-block leading-none;
|
|
||||||
|
|
||||||
&__active {
|
|
||||||
@apply outline outline-2 outline-offset-2 outline-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-changer {
|
|
||||||
@apply absolute w-80 z-20 p-4 border rounded bg-white flex gap-0 right-0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-list {
|
&-list {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { Stats, OrbitControls } from '@tresjs/cientos'
|
||||||
import { degToRad } from 'three/src/math/MathUtils.js';
|
import { degToRad } from 'three/src/math/MathUtils.js';
|
||||||
|
|
||||||
const section_count = use_section_count()
|
const section_count = use_section_count()
|
||||||
const extra_section = use_extra_section()
|
|
||||||
const fence_section = use_fence_section()
|
const fence_section = use_fence_section()
|
||||||
|
|
||||||
const defDistance = 3
|
const defDistance = 3
|
||||||
|
@ -47,12 +46,14 @@ watch(fence_section, ()=>{
|
||||||
<TresCanvas>
|
<TresCanvas>
|
||||||
<TresPerspectiveCamera v-bind="cameraStat" ref="camera" />
|
<TresPerspectiveCamera v-bind="cameraStat" ref="camera" />
|
||||||
<OrbitControls v-bind="controlsState" make-default />
|
<OrbitControls v-bind="controlsState" make-default />
|
||||||
|
<Suspense>
|
||||||
|
<ModelCamera />
|
||||||
|
</Suspense>
|
||||||
<TresGroup :position-y="-0.5">
|
<TresGroup :position-y="-0.5">
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<ModelParametric />
|
<ModelParametric />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</TresGroup>
|
</TresGroup>
|
||||||
|
|
||||||
</TresCanvas>
|
</TresCanvas>
|
||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -139,12 +139,10 @@ const changeParametres = () => {
|
||||||
|
|
||||||
|
|
||||||
const setLamelleColor = (color: ralTypes) => {
|
const setLamelleColor = (color: ralTypes) => {
|
||||||
goto_cam.value = new Vector3(-2, -2, -2)
|
|
||||||
lamelle_color.value = color;
|
lamelle_color.value = color;
|
||||||
lamelle_text.value = contrastColor(color) ?? '#000'
|
lamelle_text.value = contrastColor(color) ?? '#000'
|
||||||
}
|
}
|
||||||
const setPillarColor = (color: ralTypes) => {
|
const setPillarColor = (color: ralTypes) => {
|
||||||
goto_cam.value = new Vector3(2, 2, 2)
|
|
||||||
pillar_color.value = color
|
pillar_color.value = color
|
||||||
pillar_text.value = contrastColor(color) ?? '#000'
|
pillar_text.value = contrastColor(color) ?? '#000'
|
||||||
}
|
}
|
||||||
|
@ -225,43 +223,48 @@ const calc_table = computed(() => {
|
||||||
<input id="remove_pillar" type="checkbox" v-model="form_state.remove_pillar" />
|
<input id="remove_pillar" type="checkbox" v-model="form_state.remove_pillar" />
|
||||||
<label for="remove_pillar">Без столбов</label>
|
<label for="remove_pillar">Без столбов</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-3 col-start-10">
|
<div class="col-span-3 col-start-10">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-item form-item_color">
|
<div class="form-item form-item_color">
|
||||||
<label for="lamelle_color">Цвет ламелей</label>
|
<label for="lamelle_color">Цвет ламелей</label>
|
||||||
<DropdownColorPicker :cb="setLamelleColor">
|
<DropdownPicker type="color" :cb="setLamelleColor" name="lamelle_color">
|
||||||
<input id="lamelle_color" type="text" :value="getColorNameFromRal(lamelle_color)" :style="{
|
<input id="lamelle_color" type="text" :value="getColorNameFromRal(lamelle_color)" :style="{
|
||||||
backgroundColor: getColorHexFromRal(lamelle_color) ?? 'transparent',
|
backgroundColor: getColorHexFromRal(lamelle_color) ?? 'transparent',
|
||||||
color: lamelle_text
|
color: lamelle_text
|
||||||
}" />
|
}" />
|
||||||
</DropdownColorPicker>
|
</DropdownPicker>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item form-item_color">
|
<div class="form-item form-item_color">
|
||||||
<label for="pillar_color">Цвет столба</label>
|
<label for="pillar_color">Цвет столба</label>
|
||||||
<DropdownColorPicker :cb="setPillarColor">
|
<DropdownPicker type="color" :cb="setPillarColor" name="pillar_color">
|
||||||
<input id="pillar_color" type="text" :value="getColorNameFromRal(pillar_color)" :style="{
|
<input id="pillar_color" type="text" :value="getColorNameFromRal(pillar_color)" :style="{
|
||||||
backgroundColor: getColorHexFromRal(pillar_color) ?? 'transparent',
|
backgroundColor: getColorHexFromRal(pillar_color) ?? 'transparent',
|
||||||
color: pillar_text
|
color: pillar_text
|
||||||
}" />
|
}" />
|
||||||
</DropdownColorPicker>
|
</DropdownPicker>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item form-item_color">
|
<div class="form-item form-item_color">
|
||||||
<label for="pillar_pattern">Узор столба</label>
|
<label for="pillar_pattern">Узор столба</label>
|
||||||
<DropdownList :cb="setPillarPattern">
|
<DropdownPicker type="pattern" :cb="setPillarPattern">
|
||||||
<input id="pillar_pattern" type="text" :value="pillar_pattern" :style="{
|
<input id="pillar_pattern" type="text" :value="pillar_pattern" :style="{
|
||||||
backgroundImage: `url(${getFilename(pillar_pattern)})`}" />
|
backgroundImage: `url(${getFilename(pillar_pattern)})`
|
||||||
</DropdownList>
|
}" />
|
||||||
|
</DropdownPicker>
|
||||||
</div>
|
</div>
|
||||||
|
{{ goto_cam }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="(form_state.total_length * 1000) >= parametric.length.min">
|
<template v-if="(form_state.total_length * 1000) >= parametric.length.min">
|
||||||
<div class="col-span-12 xl:col-span-6 xl:col-start-4 grid calc_table">
|
<div class="col-span-12 xl:col-span-6 xl:col-start-4 grid calc_table">
|
||||||
<div class="grid grid-cols-4 relative">
|
<div class="grid grid-cols-4 relative">
|
||||||
<template v-for="item in calc_table">
|
<template v-for="item in calc_table">
|
||||||
<div class="col-span-3 calc_table-maincell">{{
|
<div class="col-span-3 calc_table-maincell">
|
||||||
item.name }}</div>
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
<div class="col-span-1 calc_table-maincell">{{ item.value }}</div>
|
<div class="col-span-1 calc_table-maincell">{{ item.value }}</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
@ -274,7 +277,8 @@ const calc_table = computed(() => {
|
||||||
#pillar_pattern {
|
#pillar_pattern {
|
||||||
background-clip: content-box;
|
background-clip: content-box;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
&:not([style*='url("undefined")']) {
|
|
||||||
|
&[style*='url("/'] {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ralClassicPallette, getColorHexFromRal } from '@/components/ral'
|
import { ralClassicPallette } from '@/components/ral'
|
||||||
|
|
||||||
const props = defineProps(['color', 'cb', 'open', 'active'])
|
const props = defineProps(['color', 'cb'])
|
||||||
const open = props.open ?? true
|
|
||||||
|
|
||||||
const goto_cam = use_goto_camera()
|
|
||||||
|
|
||||||
const onClick = (color: string) => {
|
|
||||||
if (props.cb) {
|
|
||||||
props.cb(color)
|
|
||||||
}
|
|
||||||
toggleOpen()
|
|
||||||
}
|
|
||||||
const isOpenPicker = ref<boolean>(false)
|
|
||||||
const toggleOpen = (value: boolean = !isOpenPicker) => {
|
|
||||||
if (value == false) {
|
|
||||||
goto_cam.value = undefined
|
|
||||||
}
|
|
||||||
isOpenPicker.value = value !== undefined ? value : !isOpenPicker.value
|
|
||||||
}
|
|
||||||
const picker = ref()
|
|
||||||
const clickOutside = (e: Event) => {
|
|
||||||
if (!picker.value.contains(e.target)) {
|
|
||||||
toggleOpen(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
document.addEventListener('click', clickOutside)
|
|
||||||
})
|
|
||||||
onUnmounted(() => {
|
|
||||||
document.removeEventListener('click', clickOutside)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="color_picker" ref="picker">
|
|
||||||
<template v-if="$slots.default">
|
|
||||||
<div @click="open ? toggleOpen(!isOpenPicker) : onClick(props.color)">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="color_picker-selected" @click="open ? toggleOpen(!isOpenPicker) : onClick(props.color)"
|
|
||||||
:style="[props.color && { backgroundColor: getColorHexFromRal(props.color) ?? '' }]"
|
|
||||||
:class="[{ 'color_picker-selected__active': active }]"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div class="color_picker-changer flex flex-wrap" v-if="isOpenPicker">
|
|
||||||
<template v-for="col in ralClassicPallette">
|
<template v-for="col in ralClassicPallette">
|
||||||
<div class="color size-5" :class="[{ 'outline outline-primary': props.color == col.hex }]"
|
<div class="color size-5" :class="[{ 'outline outline-primary': props.color == col.hex }]"
|
||||||
:style="[{ backgroundColor: col.hex }]" @click="onClick(col.code)">
|
:style="[{ backgroundColor: col.hex }]" @click="props.cb(col.code)">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
|
||||||
.color_picker-selected:not([style*=color]) {
|
|
||||||
background-image: conic-gradient(from 50deg, orange, yellow, green, cyan, blue, violet)
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,56 +1,12 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getFilename, patterns } from '../pattern';
|
import { getFilename, patterns } from '../pattern';
|
||||||
|
|
||||||
const props = defineProps(['color', 'cb', 'open', 'active'])
|
const props = defineProps(['color', 'cb'])
|
||||||
const open = props.open ?? true
|
|
||||||
const is_open = ref<boolean>(false)
|
|
||||||
const picker = ref()
|
|
||||||
|
|
||||||
const onClick = (color: string) => {
|
|
||||||
if (props.cb) {
|
|
||||||
props.cb(color)
|
|
||||||
}
|
|
||||||
toggleOpen()
|
|
||||||
}
|
|
||||||
|
|
||||||
const toggleOpen = (value: boolean = !is_open) => {
|
|
||||||
is_open.value = value !== undefined ? value : !is_open.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const clickOutside = (e: Event) => {
|
|
||||||
if (!picker.value.contains(e.target)) {
|
|
||||||
toggleOpen(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
document.addEventListener('click', clickOutside)
|
|
||||||
})
|
|
||||||
onUnmounted(() => {
|
|
||||||
document.removeEventListener('click', clickOutside)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="list_picker" ref="picker">
|
|
||||||
<template v-if="$slots.default">
|
|
||||||
<div @click="open ? toggleOpen(!is_open) : onClick(props.color)">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="list_picker-selected" @click="open ? toggleOpen(!is_open) : onClick(props.color)"
|
|
||||||
:class="[{ 'list_picker-selected__active': active }]">
|
|
||||||
<NuxtImg :src="getFilename(patterns[1].name)" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="list_picker-changer" v-if="is_open">
|
|
||||||
<div class="list_picker-list">
|
|
||||||
<template v-for="item in patterns">
|
<template v-for="item in patterns">
|
||||||
<NuxtImg :src="getFilename(item.name)" class="list_picker-item" @click="onClick(item.name)"
|
<NuxtImg :src="getFilename(item.name)" class="picker-item" @click="props.cb(item.name)"
|
||||||
v-if="item.filename" />
|
v-if="item.filename" />
|
||||||
<span class=" list_picker-item list_picker-item--empty" @click="onClick(item.name)" v-else />
|
<span class="picker-item list_picker-item--empty" @click="props.cb(item.name)" v-else />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
|
@ -0,0 +1,73 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ralClassicPallette, getColorHexFromRal } from '@/components/ral'
|
||||||
|
|
||||||
|
const props = defineProps(['color', 'cb', 'name', 'type'])
|
||||||
|
|
||||||
|
const goto_cam = use_goto_camera()
|
||||||
|
const open_calc = use_open_calc()
|
||||||
|
|
||||||
|
const picker = ref()
|
||||||
|
const is_open = ref<boolean>(open_calc.value.includes(props.name))
|
||||||
|
|
||||||
|
const toggleOpen = (value: boolean = !is_open) => {
|
||||||
|
is_open.value = value
|
||||||
|
if (value == true) open_calc.value = [props.name]
|
||||||
|
else if (value == false) open_calc.value.splice(open_calc.value.indexOf(props.name), 1)
|
||||||
|
|
||||||
|
if (value == true) goto_cam.value = undefined
|
||||||
|
else if (value == false) goto_cam.value = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClick = (color: string) => {
|
||||||
|
if (props.cb) {
|
||||||
|
props.cb(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickOutside = (e: Event) => {
|
||||||
|
if (!picker.value.contains(e.target)) {
|
||||||
|
toggleOpen(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener('click', clickOutside)
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener('click', clickOutside)
|
||||||
|
})
|
||||||
|
watch(open_calc, () => {
|
||||||
|
if (open_calc.value.includes(props.name) && is_open.value !== true) {
|
||||||
|
is_open.value = true
|
||||||
|
} else if (!open_calc.value.includes(props.name) && is_open.value !== false) {
|
||||||
|
is_open.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="picker" ref="picker">
|
||||||
|
<template v-if="$slots.default">
|
||||||
|
<div @click="toggleOpen(!is_open)">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="picker-selected" @click="toggleOpen(!is_open)"
|
||||||
|
:style="[props.color && { backgroundColor: getColorHexFromRal(props.color) ?? '' }]"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="picker-changer flex flex-wrap" v-if="is_open">
|
||||||
|
<template v-if="props.type == 'color'">
|
||||||
|
<DropdownColorPicker :color="props.color" :cb="onClick" />
|
||||||
|
</template>
|
||||||
|
<template v-else-if="props.type == 'pattern'">
|
||||||
|
<DropdownList :color="props.color" :cb="onClick" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.color_picker-selected:not([style*=color]) {
|
||||||
|
background-image: conic-gradient(from 50deg, orange, yellow, green, cyan, blue, violet)
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,50 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useLoop } from '@tresjs/core';
|
||||||
|
import { Vector3 } from 'three';
|
||||||
|
|
||||||
|
const { controls, camera } = useTresContext();
|
||||||
|
const goto_camera = use_goto_camera();
|
||||||
|
|
||||||
|
const COUNT = 30
|
||||||
|
type smooth = {
|
||||||
|
value: Vector3 | undefined,
|
||||||
|
count: number
|
||||||
|
}
|
||||||
|
const smooth_target = reactive({}) as smooth
|
||||||
|
const smooth_move = reactive({}) as smooth
|
||||||
|
|
||||||
|
const set_moveto = (obj: smooth, value: smooth["value"]) => {
|
||||||
|
obj.value = value
|
||||||
|
obj.count = COUNT
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(goto_camera, () => {
|
||||||
|
smooth_target.value = goto_camera.value
|
||||||
|
smooth_target.count = COUNT
|
||||||
|
})
|
||||||
|
|
||||||
|
const koef = (1 / COUNT) * 3
|
||||||
|
const { onBeforeLoop } = useRenderLoop()
|
||||||
|
onBeforeLoop(() => {
|
||||||
|
if (smooth_target.value || smooth_move.value) {
|
||||||
|
if (smooth_target.value) {
|
||||||
|
(controls.value as any).target.lerp(smooth_target.value as Vector3, koef);
|
||||||
|
(controls.value as any).update();
|
||||||
|
smooth_target.count -= 1;
|
||||||
|
if (smooth_target.count == 1) {
|
||||||
|
set_moveto(smooth_target, undefined);
|
||||||
|
}
|
||||||
|
} else if (smooth_move.value) {
|
||||||
|
camera.value?.position.lerp(smooth_move.value as Vector3, koef);
|
||||||
|
camera.value?.updateMatrixWorld();
|
||||||
|
(controls.value as any).update();
|
||||||
|
|
||||||
|
smooth_move.count -= 1;
|
||||||
|
if (smooth_move.count == 1) {
|
||||||
|
set_moveto(smooth_move, undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template></template>
|
|
@ -23,3 +23,4 @@ export const use_max_size = () => useState<number>('max_size', () => 20)
|
||||||
export const use_explosion_state = () => useState<boolean>('explosion_state', () => false)
|
export const use_explosion_state = () => useState<boolean>('explosion_state', () => false)
|
||||||
|
|
||||||
export const use_goto_camera = () => useState<Vector3 | undefined>('gotocam', () => undefined)
|
export const use_goto_camera = () => useState<Vector3 | undefined>('gotocam', () => undefined)
|
||||||
|
export const use_open_calc = () => useState<string[]>('open_calc', () => [])
|
|
@ -1,6 +1,7 @@
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
|
devtools: { enabled: false },
|
||||||
hooks: {},
|
hooks: {},
|
||||||
app: {
|
app: {
|
||||||
pageTransition: { name: 'page', mode: 'out-in' },
|
pageTransition: { name: 'page', mode: 'out-in' },
|
||||||
|
|
Loading…
Reference in New Issue