|
<template> |
|
<div class="element-shadow"> |
|
<div class="row"> |
|
<div style="width: 40%;">启用阴影:</div> |
|
<div class="switch-wrapper" style="width: 60%;"> |
|
<Switch :value="hasShadow" @update:value="value => toggleShadow(value)" /> |
|
</div> |
|
</div> |
|
<template v-if="hasShadow && shadow"> |
|
<div class="row"> |
|
<div style="width: 40%;">水平阴影:</div> |
|
<Slider |
|
style="width: 60%;" |
|
:min="-10" |
|
:max="10" |
|
:step="1" |
|
:value="shadow.h" |
|
@update:value="value => updateShadow({ h: value as number })" |
|
/> |
|
</div> |
|
<div class="row"> |
|
<div style="width: 40%;">垂直阴影:</div> |
|
<Slider |
|
style="width: 60%;" |
|
:min="-10" |
|
:max="10" |
|
:step="1" |
|
:value="shadow.v" |
|
@update:value="value => updateShadow({ v: value as number })" |
|
/> |
|
</div> |
|
<div class="row"> |
|
<div style="width: 40%;">模糊距离:</div> |
|
<Slider |
|
style="width: 60%;" |
|
:min="1" |
|
:max="20" |
|
:step="1" |
|
:value="shadow.blur" |
|
@update:value="value => updateShadow({ blur: value as number })" |
|
/> |
|
</div> |
|
<div class="row"> |
|
<div style="width: 40%;">阴影颜色:</div> |
|
<Popover trigger="click" style="width: 60%;"> |
|
<template #content> |
|
<ColorPicker |
|
:modelValue="shadow.color" |
|
@update:modelValue="value => updateShadow({ color: value })" |
|
/> |
|
</template> |
|
<ColorButton :color="shadow.color" /> |
|
</Popover> |
|
</div> |
|
</template> |
|
</div> |
|
</template> |
|
|
|
<script lang="ts" setup> |
|
import { ref, watch } from 'vue' |
|
import { storeToRefs } from 'pinia' |
|
import { useMainStore, useSlidesStore } from '@/store' |
|
import type { PPTElementShadow } from '@/types/slides' |
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot' |
|
|
|
import ColorButton from '@/components/ColorButton.vue' |
|
import ColorPicker from '@/components/ColorPicker/index.vue' |
|
import Switch from '@/components/Switch.vue' |
|
import Slider from '@/components/Slider.vue' |
|
import Popover from '@/components/Popover.vue' |
|
|
|
const slidesStore = useSlidesStore() |
|
const { theme } = storeToRefs(slidesStore) |
|
const { handleElement } = storeToRefs(useMainStore()) |
|
|
|
const shadow = ref<PPTElementShadow>() |
|
const hasShadow = ref(false) |
|
|
|
watch(handleElement, () => { |
|
if (!handleElement.value) return |
|
shadow.value = 'shadow' in handleElement.value ? handleElement.value.shadow : undefined |
|
hasShadow.value = !!shadow.value |
|
}, { deep: true, immediate: true }) |
|
|
|
const { addHistorySnapshot } = useHistorySnapshot() |
|
|
|
const updateShadow = (shadowProps: Partial<PPTElementShadow>) => { |
|
if (!handleElement.value || !shadow.value) return |
|
const _shadow = { ...shadow.value, ...shadowProps } |
|
slidesStore.updateElement({ id: handleElement.value.id, props: { shadow: _shadow } }) |
|
addHistorySnapshot() |
|
} |
|
|
|
const toggleShadow = (checked: boolean) => { |
|
if (!handleElement.value) return |
|
if (checked) { |
|
const _shadow: PPTElementShadow = theme.value.shadow |
|
slidesStore.updateElement({ id: handleElement.value.id, props: { shadow: _shadow } }) |
|
} |
|
else { |
|
slidesStore.removeElementProps({ id: handleElement.value.id, propName: 'shadow' }) |
|
} |
|
addHistorySnapshot() |
|
} |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.row { |
|
width: 100%; |
|
height: 30px; |
|
display: flex; |
|
align-items: center; |
|
margin-bottom: 10px; |
|
} |
|
.switch-wrapper { |
|
text-align: right; |
|
} |
|
</style> |