96 lines
2.3 KiB
Vue
96 lines
2.3 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,
|
|
},
|
|
modelValue: {
|
|
type: [String, Number],
|
|
default: '',
|
|
},
|
|
})
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
const selected = ref<string | number>('')
|
|
|
|
onMounted(() => {
|
|
if (props.modelValue) {
|
|
handle_select(props.modelValue)
|
|
} else {
|
|
handle_select(props.ratios[0].value)
|
|
}
|
|
})
|
|
|
|
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 dark:bg-neutral-700/50 rounded-lg py-1.5 flex flex-col justify-between items-center cursor-pointer select-none"
|
|
:class="[ratio.value === selected && 'bg-sky-200/50 dark:bg-sky-700/50']"
|
|
>
|
|
<div
|
|
class="bg-neutral-300/50 dark:bg-neutral-600/50 text-neutral-600 dark:text-neutral-300 rounded flex justify-center items-center"
|
|
:class="[
|
|
ratio.value === selected && 'bg-sky-300/50 dark:bg-sky-600/50',
|
|
]"
|
|
:style="{
|
|
width: getShapeSize(getRatio(ratio.ratio), 30).w * 1.1 + 'px',
|
|
height: getShapeSize(getRatio(ratio.ratio), 30).h * 1.1 + 'px',
|
|
}"
|
|
>
|
|
<span class="text-xs font-thin font-mono">{{ ratio.ratio }}</span>
|
|
</div>
|
|
<span class="text-[10px]">
|
|
{{
|
|
ratio?.label || getRatio(ratio.ratio).w === getRatio(ratio.ratio).h
|
|
? '正方形'
|
|
: getRatio(ratio.ratio).w > getRatio(ratio.ratio).h
|
|
? '横向'
|
|
: '纵向'
|
|
}}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|