dev #84
|
@ -345,8 +345,10 @@ button {
|
||||||
&_checkbox {
|
&_checkbox {
|
||||||
@apply w-full xl:w-auto flex-row xl:flex-initial flex-nowrap gap-4;
|
@apply w-full xl:w-auto flex-row xl:flex-initial flex-nowrap gap-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_color {
|
&_color {
|
||||||
@apply w-full;
|
@apply w-full;
|
||||||
|
|
||||||
.color_picker {
|
.color_picker {
|
||||||
@apply ml-4;
|
@apply ml-4;
|
||||||
}
|
}
|
||||||
|
@ -374,6 +376,34 @@ button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
@apply flex gap-4 w-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
@apply w-10 h-10;
|
||||||
|
&--empty {
|
||||||
|
@apply block bg-slate-300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.feature {
|
.feature {
|
||||||
@apply col-span-full flex gap-10 mt-4 justify-center xl:justify-between flex-wrap items-center;
|
@apply col-span-full flex gap-10 mt-4 justify-center xl:justify-between flex-wrap items-center;
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getColorNameFromRal } from '@/components/ral'
|
import { getColorHexFromRal, getColorNameFromRal } from '@/components/ral'
|
||||||
import type { ralTypes } from '@/components/ral'
|
import type { ralTypes } from '@/components/ral'
|
||||||
|
|
||||||
import { predefLamelleColors, predefPillarColors } from '~/composables/useCalc';
|
import { predefLamelleColors, predefPillarColors } from '~/composables/useCalc';
|
||||||
|
import type { patternTypes } from '../pattern';
|
||||||
|
|
||||||
const lamelle_height = use_lamelle_height()
|
const lamelle_height = use_lamelle_height()
|
||||||
const lamelles_count = use_lamelles_count()
|
const lamelles_count = use_lamelles_count()
|
||||||
const fence_section = use_fence_section()
|
const fence_section = use_fence_section()
|
||||||
const remove_pillar = use_remove_pillar()
|
const remove_pillar = use_remove_pillar()
|
||||||
const pillar_color = use_pillar_color()
|
const pillar_color = use_pillar_color()
|
||||||
|
const pillar_pattern = use_pattern()
|
||||||
const lamelle_color = use_lamelle_color()
|
const lamelle_color = use_lamelle_color()
|
||||||
const section_count = use_section_count()
|
const section_count = use_section_count()
|
||||||
const extra_section = use_extra_section()
|
const extra_section = use_extra_section()
|
||||||
|
@ -56,6 +58,9 @@ const form_refs = {
|
||||||
total_length: ref(),
|
total_length: ref(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lamelle_text = ref(contrastColor(lamelle_color.value))
|
||||||
|
const pillar_text = ref(contrastColor(pillar_color.value))
|
||||||
|
|
||||||
const changeParametres = () => {
|
const changeParametres = () => {
|
||||||
// console.log('form', form_state.total_length * 1000, 'copy', copy_form_state.total_length * 1000)
|
// console.log('form', form_state.total_length * 1000, 'copy', copy_form_state.total_length * 1000)
|
||||||
|
|
||||||
|
@ -130,11 +135,17 @@ const changeParametres = () => {
|
||||||
goal('calc_fence', form_state)
|
goal('calc_fence', form_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const setLamelleColor = (color: ralTypes) => {
|
const setLamelleColor = (color: ralTypes) => {
|
||||||
lamelle_color.value = color
|
lamelle_color.value = color;
|
||||||
|
lamelle_text.value = contrastColor(color) ?? '#000'
|
||||||
}
|
}
|
||||||
const setPillarColor = (color: ralTypes) => {
|
const setPillarColor = (color: ralTypes) => {
|
||||||
pillar_color.value = color
|
pillar_color.value = color
|
||||||
|
pillar_text.value = contrastColor(color) ?? '#000'
|
||||||
|
}
|
||||||
|
const setPillarPattern = (pattern:patternTypes) => {
|
||||||
|
pillar_pattern.value = pattern
|
||||||
}
|
}
|
||||||
watch(() => form_state, changeParametres, { deep: true })
|
watch(() => form_state, changeParametres, { deep: true })
|
||||||
|
|
||||||
|
@ -202,7 +213,7 @@ const calc_table = computed(() => {
|
||||||
<input id="auto_length" type="checkbox" v-model="form_state.auto_length" />
|
<input id="auto_length" type="checkbox" v-model="form_state.auto_length" />
|
||||||
<label for="auto_length">Автоматический подбор секции</label>
|
<label for="auto_length">Автоматический подбор секции</label>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="form_state.extra_section" class="text-ioprim text-sm">
|
<p v-if="!form_state.auto_length" class="text-ioprim text-sm">
|
||||||
Рекомендуем вам включить автоподбор длины секции
|
Рекомендуем вам включить автоподбор длины секции
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -216,15 +227,24 @@ const calc_table = computed(() => {
|
||||||
<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>
|
||||||
<input id="lamelle_color" type="text" :value="getColorNameFromRal(lamelle_color)" class="w-60"
|
<input id="lamelle_color" type="text" :value="getColorNameFromRal(lamelle_color)" :style="{
|
||||||
disabled />
|
backgroundColor: getColorHexFromRal(lamelle_color) ?? 'transparent',
|
||||||
<ColorPicker :cb="setLamelleColor" />
|
color: lamelle_text
|
||||||
|
}" disabled />
|
||||||
|
<DropdownColorPicker :cb="setLamelleColor" />
|
||||||
</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>
|
||||||
<input id="pillar_color" type="text" :value="getColorNameFromRal(pillar_color)" class="w-60"
|
<input id="pillar_color" type="text" :value="getColorNameFromRal(pillar_color)" :style="{
|
||||||
disabled />
|
backgroundColor: getColorHexFromRal(pillar_color) ?? 'transparent',
|
||||||
<ColorPicker :cb="setPillarColor" />
|
color: pillar_text
|
||||||
|
}" disabled />
|
||||||
|
<DropdownColorPicker :cb="setPillarColor" />
|
||||||
|
</div>
|
||||||
|
<div class="form-item form-item_color">
|
||||||
|
<label for="pattern">Узор</label>
|
||||||
|
<input id="pattern" type="text" :value="pillar_pattern" />
|
||||||
|
<DropdownList :cb="setPillarPattern" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { getFilename, patterns } from '../pattern';
|
||||||
|
|
||||||
|
const props = defineProps(['color', 'cb', 'open', 'active'])
|
||||||
|
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>
|
||||||
|
<template>
|
||||||
|
<div class="list_picker" ref="picker">
|
||||||
|
<div class="list_picker-selected" @click="open ? toggleOpen(!is_open) : onClick(props.color)"
|
||||||
|
:class="[{ 'list_picker-selected__active': active }]">
|
||||||
|
pick
|
||||||
|
</div>
|
||||||
|
<div class="list_picker-changer" v-if="is_open">
|
||||||
|
<div class="list_picker-list">
|
||||||
|
<template v-for="item in patterns">
|
||||||
|
<NuxtImg :src="getFilename(item.name)" class="list_picker-item" @click="onClick(item.name)"
|
||||||
|
v-if="item.filename" />
|
||||||
|
<span class=" list_picker-item list_picker-item--empty" @click="onClick(item.name)" v-else />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -13,8 +13,10 @@ import { GainMapLoader, } from '@monogrid/gainmap-js'
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
import { useGLTF, } from '@tresjs/cientos'
|
import { useGLTF, } from '@tresjs/cientos'
|
||||||
import { getColorHexFromRal, type ralTypes } from '../ral';
|
import { getColorHexFromRal, type ralTypes } from '../ral';
|
||||||
|
import { getFilename } from '../pattern';
|
||||||
|
|
||||||
const pillar_color = use_pillar_color()
|
const pillar_color = use_pillar_color()
|
||||||
|
const pillar_pattern = use_pattern()
|
||||||
const lamelle_color = use_lamelle_color()
|
const lamelle_color = use_lamelle_color()
|
||||||
const section_count = use_section_count()
|
const section_count = use_section_count()
|
||||||
const lamelle_count = use_lamelles_count()
|
const lamelle_count = use_lamelles_count()
|
||||||
|
@ -76,8 +78,6 @@ watch(lamelle_color, () => {
|
||||||
watch(pillar_color, () => {
|
watch(pillar_color, () => {
|
||||||
[top, fastening, fence, fence_bottom, fence_top].map(
|
[top, fastening, fence, fence_bottom, fence_top].map(
|
||||||
(el: Ref) => { set_material(el.value, getColorHexFromRal(pillar_color.value)) });
|
(el: Ref) => { set_material(el.value, getColorHexFromRal(pillar_color.value)) });
|
||||||
[fence_inner].map(
|
|
||||||
(el: Ref) => { set_material(el.value, getColorHexFromRal(pillar_color.value), lamelle_count.value) });
|
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
...seekAll(scene.value, 'name', "pillar_one"),
|
...seekAll(scene.value, 'name', "pillar_one"),
|
||||||
|
@ -90,6 +90,15 @@ watch(pillar_color, () => {
|
||||||
set_material(element, getColorHexFromRal(pillar_color.value))
|
set_material(element, getColorHexFromRal(pillar_color.value))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
watch([pillar_color, pillar_pattern], () => {
|
||||||
|
[fence_inner].map(
|
||||||
|
(el: Ref) => {
|
||||||
|
set_material(el.value, getColorHexFromRal(pillar_color.value), {
|
||||||
|
pattern: pillar_pattern.value,
|
||||||
|
count: lamelle_count.value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
const total = ref((section_count.value + ~~(!!extra_section.value)))
|
const total = ref((section_count.value + ~~(!!extra_section.value)))
|
||||||
const size = ref(Math.ceil(total.value / 4))
|
const size = ref(Math.ceil(total.value / 4))
|
||||||
|
@ -154,8 +163,8 @@ onMounted(async () => {
|
||||||
<template>
|
<template>
|
||||||
<TresGroup name="base">
|
<TresGroup name="base">
|
||||||
<template v-for="line in (total >= 4) ? 4 : 1" :key="`${line}_${count}`">
|
<template v-for="line in (total >= 4) ? 4 : 1" :key="`${line}_${count}`">
|
||||||
<ModelLine :models="{ top, fence, fence_top, fence_bottom, fence_inner, fastening, lamelle }"
|
<ModelLine :models="{ top, fence, fence_top, fence_bottom, fence_inner, fastening, lamelle }" :number="line"
|
||||||
:number="line" :count="count" />
|
:count="count" />
|
||||||
</template>
|
</template>
|
||||||
</TresGroup>
|
</TresGroup>
|
||||||
</template>
|
</template>
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const patterns = [
|
||||||
|
{ name: 'no pattern', },
|
||||||
|
{ name: 'pattern1', filename: 'tile1.png' },
|
||||||
|
{ name: 'pattern2', filename: 'tile1.png' },
|
||||||
|
]
|
||||||
|
export const getFilename = (name: patternTypes) => {
|
||||||
|
return `/pattern/${patterns.find(el => el.name == name)?.filename}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export type patternTypes = typeof patterns[number]['name']
|
|
@ -1,7 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
const props = defineProps(['forms', 'n'])
|
|
||||||
const ruOrdinalRules = new Intl.PluralRules("ru-RU");
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
{{ props.forms[ruOrdinalRules.select(props.n)] }}
|
|
||||||
</template>
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { ralTypes } from '@/components/ral'
|
import type { ralTypes } from '@/components/ral'
|
||||||
|
import { type patternTypes } from '~/components/pattern'
|
||||||
|
|
||||||
export const predefPillarColors = ['3004', '7043', '6028', '5013', '8016', '1020', '3005', '4009']
|
export const predefPillarColors = ['3004', '7043', '6028', '5013', '8016', '1020', '3005', '4009']
|
||||||
export const predefLamelleColors = ['3009', '9003', '6027', '5024', '9001', '1012', '3007', '4007']
|
export const predefLamelleColors = ['3009', '9003', '6027', '5024', '9001', '1012', '3007', '4007']
|
||||||
|
@ -12,6 +13,7 @@ export const use_fence_section = () => useState<number>('fence_section', () => m
|
||||||
export const use_remove_pillar = () => useState<boolean>('remove_pillar', () => false)
|
export const use_remove_pillar = () => useState<boolean>('remove_pillar', () => false)
|
||||||
export const use_pillar_color = () => useState<ralTypes>('pillar_color')
|
export const use_pillar_color = () => useState<ralTypes>('pillar_color')
|
||||||
export const use_lamelle_color = () => useState<ralTypes>('lamelle_color')
|
export const use_lamelle_color = () => useState<ralTypes>('lamelle_color')
|
||||||
|
export const use_pattern = () => useState<patternTypes>('pattern')
|
||||||
export const use_section_count = () => useState('section_count', () => n)
|
export const use_section_count = () => useState('section_count', () => n)
|
||||||
export const use_extra_section = () => useState('extra_section', () => 0)
|
export const use_extra_section = () => useState('extra_section', () => 0)
|
||||||
export const use_total_length = () => useState('total_length', () => (((min + 104) * n) + 104) * 0.001)
|
export const use_total_length = () => useState('total_length', () => (((min + 104) * n) + 104) * 0.001)
|
||||||
|
|
|
@ -37,7 +37,7 @@ export default defineNuxtConfig({
|
||||||
'/index.php': { redirect: '/' },
|
'/index.php': { redirect: '/' },
|
||||||
},
|
},
|
||||||
nitro: {
|
nitro: {
|
||||||
minify: false,
|
// minify: false,
|
||||||
prerender: {
|
prerender: {
|
||||||
crawlLinks: false
|
crawlLinks: false
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="siteblock siteblock_calc bg-white">
|
<div class="siteblock siteblock_calc bg-white">
|
||||||
<CalcValues />
|
<CalcValues />
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<CalcModels />
|
<LazyCalcModels />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,18 @@
|
||||||
|
import { Color } from 'three';
|
||||||
|
import { type ralTypes } from './../components/ral';
|
||||||
|
import { getColorHexFromRal } from "~/components/ral"
|
||||||
|
|
||||||
|
export const contrastColor = (color: ralTypes) => {
|
||||||
|
const hex = getColorHexFromRal(color)
|
||||||
|
if (hex) {
|
||||||
|
const hsl = { h: 0, s: 0, l: 0 }
|
||||||
|
new Color(hex).getHSL(hsl)
|
||||||
|
if (hsl.l < 0.5) {
|
||||||
|
return '#fff'
|
||||||
|
} else {
|
||||||
|
return '#000'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return '#000'
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { Color, DoubleSide, MeshBasicMaterial, MeshStandardMaterial, RepeatWrapping, TextureLoader, Vector2 } from "three"
|
import { Color, DoubleSide, MeshBasicMaterial, MeshStandardMaterial, RepeatWrapping, TextureLoader, Vector2 } from "three"
|
||||||
import { useLoader, type TresLoader } from '@tresjs/core'
|
import { useLoader, type TresLoader } from '@tresjs/core'
|
||||||
|
import { getFilename, type patternTypes } from "~/components/pattern"
|
||||||
|
|
||||||
const set_metaril_func = (scene: any, material: any) => {
|
const set_metaril_func = (scene: any, material: any) => {
|
||||||
scene.children.forEach((el: any) => {
|
scene.children.forEach((el: any) => {
|
||||||
|
@ -19,22 +20,30 @@ const set_metaril_func = (scene: any, material: any) => {
|
||||||
// const texture = await get_texture()
|
// const texture = await get_texture()
|
||||||
// texture.wrapT = RepeatWrapping;
|
// texture.wrapT = RepeatWrapping;
|
||||||
|
|
||||||
export const set_material = (scene: any, color: any, count: number | undefined = undefined) => {
|
export const set_material = (scene: any, color: any, pattern: { pattern: patternTypes, count: number } | undefined = undefined) => {
|
||||||
let c = color
|
let c = color
|
||||||
// if (count) {
|
|
||||||
// // console.log(texture)
|
|
||||||
// texture.repeat.set(1, count);
|
|
||||||
// texture.needsUpdate = true
|
|
||||||
// }
|
|
||||||
|
|
||||||
const material = new MeshStandardMaterial({
|
const material = new MeshStandardMaterial({
|
||||||
color: new Color(c || '#9c9c00'),
|
color: new Color(c || '#9c9c00'),
|
||||||
// alphaMap: count ? texture : null,
|
// alphaMap: pattern ? texture : null,
|
||||||
transparent: true,
|
transparent: true,
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
roughness: 0.2,
|
roughness: 0.2,
|
||||||
metalness: 0,
|
metalness: 0,
|
||||||
side: DoubleSide,
|
side: DoubleSide,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (pattern && pattern.pattern !== undefined) {
|
||||||
|
const filename = getFilename(pattern.pattern)
|
||||||
|
const texture = useLoader(TextureLoader, filename)
|
||||||
|
texture.then(res => {
|
||||||
|
res.wrapT = RepeatWrapping;
|
||||||
|
res.repeat.set(1, pattern.count);
|
||||||
|
res.needsUpdate = true
|
||||||
|
// return res
|
||||||
|
material.alphaMap = res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
set_metaril_func(scene, material)
|
set_metaril_func(scene, material)
|
||||||
}
|
}
|
Loading…
Reference in New Issue