Files
xsh-assistant-next/components/aigc/RatioSelector.vue
2024-03-13 18:07:15 +08:00

68 lines
1.7 KiB
Vue

<script setup lang="ts">
import type {PropType} from "vue";
const props = defineProps({
ratios: {
type: Array as PropType<{
ratio: string,
label?: string,
value: string | number
}[]>,
required: true
}
})
const emit = defineEmits(['update:modelValue'])
const selected = ref<string | number>('')
const handle_select = (value: string | number) => {
selected.value = value
emit('update:modelValue', value)
}
const getRatio = (ratio: string) => {
const [w, h] = ratio.split(/[:\/]/).map(Number)
return {
w: w,
h: h
}
}
const getShapeSize = (r: { w: number, h: number }, size: number) => {
const ratio = r.w / r.h
if (r.w > r.h) {
return {
w: size,
h: size / ratio
}
} else {
return {
w: size * ratio,
h: size
}
}
}
</script>
<template>
<div class="grid grid-cols-4 gap-2">
<div v-for="(ratio, k) in ratios" :key="ratio.value" @click="handle_select(ratio.value)"
class="w-full aspect-square bg-neutral-200/50 rounded-lg flex flex-col justify-around items-center cursor-pointer"
:class="[ratio.value === selected && 'bg-sky-200/50']">
<div class="bg-neutral-300/50 text-neutral-900 rounded flex justify-center items-center"
:class="[ratio.value === selected && 'bg-sky-300/50']" :style="{
width: getShapeSize(getRatio(ratio.ratio), 30).w * 2 + '%',
height: getShapeSize(getRatio(ratio.ratio), 30).h * 2 + '%'
}">
<span class="text-xs font-thin">{{ ratio.ratio }}</span>
</div>
<span class="text-[10px]">
{{ ratio?.label || getRatio(ratio.ratio).w > getRatio(ratio.ratio).h ? '横向' : '纵向' }}
</span>
</div>
</div>
</template>
<style scoped>
</style>