11
This commit is contained in:
133
src/components/subtitle/TitleLineStyleEditor.vue
Normal file
133
src/components/subtitle/TitleLineStyleEditor.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<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 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: `${Math.min(Number(line.value.fontSize) || 80, 48)}px`,
|
||||
color: line.value.fontColor || "#fff",
|
||||
backgroundColor:
|
||||
enableBackground.value && line.value.backgroundColor !== "transparent"
|
||||
? line.value.backgroundColor
|
||||
: "transparent",
|
||||
textShadow: shadows.join(", ") || "none",
|
||||
padding: "8px 16px",
|
||||
};
|
||||
});
|
||||
</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>
|
||||
|
||||
<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="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" />
|
||||
<input v-model="line.shadowColor" type="color" class="h-8 w-10" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="mb-2 text-sm font-medium text-slate-700">效果预览</div>
|
||||
<div class="rounded bg-slate-100 py-4 text-center" :style="previewStyle">
|
||||
{{ line.text || "标题文字" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user