bak
This commit is contained in:
1 parent
6b6157d786
commit
3ef5fb5a2d
19 files changed
+1244
-94
No files matched your search
@@ -34,6 +34,76 @@ const textAsset = computed(() => {
|
||||
return a && a.kind === 'text' ? a : null
|
||||
})
|
||||
|
||||
const blurAsset = computed(() => {
|
||||
const a = selectedAsset.value
|
||||
return a && (a.kind === 'rect' || a.kind === 'circle') ? a : null
|
||||
})
|
||||
|
||||
const blurValue = computed<number>({
|
||||
get: () => {
|
||||
const a = blurAsset.value
|
||||
if (!a) return 0
|
||||
return sampled.value?.blur ?? a.blur ?? 0
|
||||
},
|
||||
set: (v: number) => {
|
||||
if (!selected.value) return
|
||||
store.upsertKeyframe(selected.value.id, store.playhead, { blur: v })
|
||||
},
|
||||
})
|
||||
|
||||
type ShadowNumKey = 'shadowBlur' | 'shadowOpacity' | 'shadowAngle' | 'shadowDistance'
|
||||
|
||||
interface ShadowAll {
|
||||
shadowBlur: number
|
||||
shadowOpacity: number
|
||||
shadowAngle: number
|
||||
shadowDistance: number
|
||||
shadowColor: string
|
||||
}
|
||||
|
||||
const SHADOW_DEFAULTS: ShadowAll = {
|
||||
shadowBlur: 8,
|
||||
shadowOpacity: 0,
|
||||
shadowAngle: 90,
|
||||
shadowDistance: 6,
|
||||
shadowColor: '#000000',
|
||||
}
|
||||
|
||||
function currentShadow(): ShadowAll {
|
||||
const samp = sampled.value
|
||||
return {
|
||||
shadowBlur: samp?.shadowBlur ?? SHADOW_DEFAULTS.shadowBlur,
|
||||
shadowOpacity: samp?.shadowOpacity ?? SHADOW_DEFAULTS.shadowOpacity,
|
||||
shadowAngle: samp?.shadowAngle ?? SHADOW_DEFAULTS.shadowAngle,
|
||||
shadowDistance: samp?.shadowDistance ?? SHADOW_DEFAULTS.shadowDistance,
|
||||
shadowColor: samp?.shadowColor ?? SHADOW_DEFAULTS.shadowColor,
|
||||
}
|
||||
}
|
||||
|
||||
function writeShadow(patch: Partial<ShadowAll>) {
|
||||
if (!selected.value) return
|
||||
const next = { ...currentShadow(), ...patch }
|
||||
store.upsertKeyframe(selected.value.id, store.playhead, next)
|
||||
}
|
||||
|
||||
function shadowBinding(key: ShadowNumKey, decimals = 0) {
|
||||
const factor = 10 ** decimals
|
||||
return computed({
|
||||
get: () => Math.round(currentShadow()[key] * factor) / factor,
|
||||
set: (v: number) => writeShadow({ [key]: v } as Partial<ShadowAll>),
|
||||
})
|
||||
}
|
||||
|
||||
const shadowBlur = shadowBinding('shadowBlur')
|
||||
const shadowOpacity = shadowBinding('shadowOpacity', 2)
|
||||
const shadowAngle = shadowBinding('shadowAngle')
|
||||
const shadowDistance = shadowBinding('shadowDistance')
|
||||
|
||||
const shadowColorValue = computed<string>({
|
||||
get: () => currentShadow().shadowColor,
|
||||
set: (v: string) => writeShadow({ shadowColor: v }),
|
||||
})
|
||||
|
||||
const canFill = computed(() => {
|
||||
const a = selectedAsset.value
|
||||
return !!a && (a.kind === 'rect' || a.kind === 'circle' || a.kind === 'text')
|
||||
@@ -108,6 +178,71 @@ function removeKeyframeHere() {
|
||||
<label>Text<input type="text" v-model="textAsset.text" /></label>
|
||||
<label>Font Size<input type="number" min="1" v-model.number="textAsset.fontSize" /></label>
|
||||
</template>
|
||||
<label v-if="blurAsset" class="slider-label">
|
||||
{{ t('properties.edgeBlur') }}
|
||||
<RangeSlider
|
||||
v-model="blurValue"
|
||||
:min="0"
|
||||
:max="64"
|
||||
:step="1"
|
||||
:format="(v: number) => `${Math.round(v)}px`"
|
||||
/>
|
||||
</label>
|
||||
<section class="shadow-group">
|
||||
<h4>{{ t('properties.shadow') }}</h4>
|
||||
<label class="color-label">
|
||||
{{ t('properties.shadowColor') }}
|
||||
<div class="color-row">
|
||||
<input
|
||||
type="color"
|
||||
class="color-swatch"
|
||||
:value="shadowColorValue"
|
||||
@input="shadowColorValue = ($event.target as HTMLInputElement).value"
|
||||
/>
|
||||
<span class="color-hex">{{ shadowColorValue.toUpperCase() }}</span>
|
||||
</div>
|
||||
</label>
|
||||
<label class="slider-label">
|
||||
{{ t('properties.shadowOpacity') }}
|
||||
<RangeSlider
|
||||
v-model="shadowOpacity"
|
||||
:min="0"
|
||||
:max="1"
|
||||
:step="0.01"
|
||||
:format="formatPercent"
|
||||
/>
|
||||
</label>
|
||||
<label class="slider-label">
|
||||
{{ t('properties.shadowBlur') }}
|
||||
<RangeSlider
|
||||
v-model="shadowBlur"
|
||||
:min="0"
|
||||
:max="64"
|
||||
:step="1"
|
||||
:format="(v: number) => `${Math.round(v)}px`"
|
||||
/>
|
||||
</label>
|
||||
<label class="slider-label">
|
||||
{{ t('properties.shadowDistance') }}
|
||||
<RangeSlider
|
||||
v-model="shadowDistance"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="1"
|
||||
:format="(v: number) => `${Math.round(v)}px`"
|
||||
/>
|
||||
</label>
|
||||
<label class="slider-label">
|
||||
{{ t('properties.shadowAngle') }}
|
||||
<RangeSlider
|
||||
v-model="shadowAngle"
|
||||
:min="0"
|
||||
:max="360"
|
||||
:step="1"
|
||||
:format="(v: number) => `${Math.round(v)}°`"
|
||||
/>
|
||||
</label>
|
||||
</section>
|
||||
<label v-if="canFill" class="color-label">
|
||||
Color
|
||||
<div class="color-row">
|
||||
@@ -180,6 +315,23 @@ input {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.shadow-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.shadow-group h4 {
|
||||
margin: 0;
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--text-dim);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.kf-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user