Files
yaoayanui/src/components/subtitle/TitleLineStyleEditor.vue
949036910@qq.com 8fc42958c3 11
2026-05-27 20:40:22 +08:00

168 lines
5.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { computed } from "vue";
import { SUBTITLE_FONT_OPTIONS } from "../../config/subtitleStylePresets.js";
const line = defineModel("line", { type: Object, required: true });
const enableBackground = computed({
get: () =>
line.value.backgroundColor &&
line.value.backgroundColor !== "transparent" &&
(line.value.backgroundOpacity ?? 0) > 0,
set: (on) => {
if (on) {
line.value.backgroundColor = line.value.backgroundColor || "#000000";
line.value.backgroundOpacity = line.value.backgroundOpacity || 0.5;
} else {
line.value.backgroundColor = "transparent";
line.value.backgroundOpacity = 0;
}
},
});
const backgroundOpacityPercent = computed({
get: () => Math.round((Number(line.value.backgroundOpacity) || 0) * 100),
set: (value) => {
line.value.backgroundOpacity = Math.max(0, Math.min(100, Number(value) || 0)) / 100;
},
});
const enableShadow = computed({
get: () => (line.value.shadowOffset ?? 0) > 0,
set: (on) => {
line.value.shadowOffset = on ? line.value.shadowOffset || 2 : 0;
},
});
const previewStyle = computed(() => {
const outline = Number(line.value.outlineWidth) || 0;
const offset = Number(line.value.shadowOffset) || 0;
const shadows = [];
if (outline > 0) {
const c = line.value.outlineColor || "#000";
for (let x = -outline; x <= outline; x++) {
for (let y = -outline; y <= outline; y++) {
if (x || y) shadows.push(`${x}px ${y}px 0 ${c}`);
}
}
}
if (offset > 0) {
shadows.push(`${offset}px ${offset}px 0 ${line.value.shadowColor || "#000"}`);
}
return {
fontFamily: line.value.fontName ? `'${line.value.fontName}'` : "优设标题黑",
fontSize: `${Number(line.value.fontSize) || 80}px`,
color: line.value.fontColor || "#fff",
backgroundColor:
enableBackground.value && line.value.backgroundColor !== "transparent"
? line.value.backgroundColor
: "transparent",
textShadow: shadows.join(", ") || "none",
padding: "8px 16px",
display: "inline-block",
lineHeight: 1.12,
};
});
</script>
<template>
<div class="line-style-editor space-y-4 text-slate-800">
<div>
<div class="mb-2 text-sm font-medium text-slate-700">字体设置</div>
<div class="space-y-3">
<div>
<label class="mb-1 block text-xs text-slate-500">字体</label>
<Select
v-model="line.fontName"
:options="SUBTITLE_FONT_OPTIONS"
option-label="label"
option-value="value"
class="w-full"
size="small"
/>
</div>
<div>
<label class="mb-1 block text-xs text-slate-500">字体大小像素</label>
<InputNumber v-model="line.fontSize" :min="24" :max="120" class="w-full" size="small" />
</div>
</div>
</div>
<div>
<div class="mb-2 text-sm font-medium text-slate-700">颜色设置</div>
<div class="flex items-center gap-2">
<input v-model="line.fontColor" type="color" class="h-8 w-10" />
<span class="font-mono text-xs">{{ line.fontColor }}</span>
</div>
</div>
<div>
<div class="mb-2 text-sm font-medium text-slate-700">描边设置</div>
<div class="space-y-2">
<div class="flex items-center gap-2">
<label class="text-xs text-slate-500">描边宽度</label>
<Slider v-model="line.outlineWidth" :min="0" :max="10" class="flex-1" />
<span class="w-8 text-right text-xs">{{ line.outlineWidth }}</span>
</div>
<div class="flex items-center gap-2">
<label class="text-xs text-slate-500">描边颜色</label>
<input v-model="line.outlineColor" type="color" class="h-8 w-10" />
</div>
</div>
</div>
<div>
<div class="mb-2 text-sm font-medium text-slate-700">背景设置</div>
<label class="flex items-center gap-2 text-sm">
<Checkbox v-model="enableBackground" binary />
启用背景
</label>
<div v-if="enableBackground" class="mt-2 grid grid-cols-2 gap-3">
<div>
<label class="mb-1 block text-xs text-slate-500">背景颜色</label>
<div class="flex items-center gap-2">
<input v-model="line.backgroundColor" type="color" class="h-8 w-10" />
<InputText v-model="line.backgroundColor" size="small" class="flex-1" />
</div>
</div>
<div>
<label class="mb-1 block text-xs text-slate-500">背景透明度</label>
<div class="flex items-center gap-2">
<Slider v-model="backgroundOpacityPercent" :min="0" :max="100" class="flex-1" />
<span class="w-10 text-right text-xs">{{ backgroundOpacityPercent }}%</span>
</div>
</div>
</div>
</div>
<div>
<div class="mb-2 text-sm font-medium text-slate-700">阴影设置可选</div>
<label class="mb-2 flex items-center gap-2 text-sm">
<Checkbox v-model="enableShadow" binary />
启用阴影
</label>
<div v-if="enableShadow" class="space-y-2">
<div class="flex items-center gap-2">
<label class="text-xs text-slate-500">阴影偏移</label>
<Slider v-model="line.shadowOffset" :min="1" :max="10" class="flex-1" />
<span class="w-8 text-right text-xs">{{ line.shadowOffset }}</span>
</div>
<div class="flex items-center gap-2">
<label class="text-xs text-slate-500">阴影颜色</label>
<input v-model="line.shadowColor" type="color" class="h-8 w-10" />
<InputText v-model="line.shadowColor" size="small" class="flex-1" />
</div>
</div>
</div>
<div>
<div class="mb-2 text-sm font-medium text-slate-700">效果预览</div>
<div class="overflow-hidden rounded bg-slate-100 py-4 text-center">
<div :style="previewStyle">
{{ line.text || "标题文字" }}
</div>
</div>
</div>
</div>
</template>