mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
perf: 线条、边框样式配置项优化
This commit is contained in:
parent
c767934b69
commit
bc6a51e5c7
120
src/components/SelectCustom.vue
Normal file
120
src/components/SelectCustom.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="select-wrap" v-if="disabled">
|
||||
<div class="select disabled" ref="selectRef">
|
||||
<div class="selector"><slot name="label"></slot></div>
|
||||
<div class="icon">
|
||||
<slot name="icon">
|
||||
<IconDown :size="14" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Popover
|
||||
class="select-wrap"
|
||||
trigger="click"
|
||||
v-model:value="popoverVisible"
|
||||
placement="bottom"
|
||||
:contentStyle="{
|
||||
padding: 0,
|
||||
boxShadow: '0 6px 16px 0 rgba(0, 0, 0, 0.08)',
|
||||
}"
|
||||
v-else
|
||||
>
|
||||
<template #content>
|
||||
<div class="options" :style="{ width: width + 2 + 'px' }" @click="popoverVisible = false">
|
||||
<slot name="options"></slot>
|
||||
</div>
|
||||
</template>
|
||||
<div class="select" ref="selectRef">
|
||||
<div class="selector"><slot name="label"></slot></div>
|
||||
<div class="icon">
|
||||
<slot name="icon">
|
||||
<IconDown :size="14" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</Popover>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import Popover from './Popover.vue'
|
||||
|
||||
withDefaults(defineProps<{
|
||||
disabled?: boolean
|
||||
}>(), {
|
||||
disabled: false,
|
||||
})
|
||||
|
||||
const popoverVisible = ref(false)
|
||||
const selectRef = ref<HTMLElement>()
|
||||
const width = ref(0)
|
||||
|
||||
const updateWidth = () => {
|
||||
if (!selectRef.value) return
|
||||
width.value = selectRef.value.clientWidth
|
||||
}
|
||||
const resizeObserver = new ResizeObserver(updateWidth)
|
||||
onMounted(() => {
|
||||
if (!selectRef.value) return
|
||||
resizeObserver.observe(selectRef.value)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
if (!selectRef.value) return
|
||||
resizeObserver.unobserve(selectRef.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select {
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding-right: 32px;
|
||||
border-radius: $borderRadius;
|
||||
transition: border-color .25s;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
background-color: #fff;
|
||||
border: 1px solid #d9d9d9;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
&:not(.disabled):hover {
|
||||
border-color: $themeColor;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background-color: #f5f5f5;
|
||||
border-color: #dcdcdc;
|
||||
color: #b7b7b7;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.selector {
|
||||
min-width: 50px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-left: 10px;
|
||||
@include ellipsis-oneline();
|
||||
}
|
||||
}
|
||||
.options {
|
||||
max-height: 260px;
|
||||
padding: 5px;
|
||||
overflow: auto;
|
||||
text-align: left;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
}
|
||||
.icon {
|
||||
width: 32px;
|
||||
height: 30px;
|
||||
color: #bfbfbf;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
@ -1,9 +1,9 @@
|
||||
import type { LinePoint } from '@/types/slides'
|
||||
import type { LinePoint, LineStyleType } from '@/types/slides'
|
||||
|
||||
|
||||
export interface LinePoolItem {
|
||||
path: string
|
||||
style: 'solid' | 'dashed'
|
||||
style: LineStyleType
|
||||
points: [LinePoint, LinePoint]
|
||||
isBroken?: boolean
|
||||
isBroken2?: boolean
|
||||
|
@ -52,6 +52,8 @@ export interface Gradient {
|
||||
rotate: number
|
||||
}
|
||||
|
||||
export type LineStyleType = 'solid' | 'dashed' | 'dotted'
|
||||
|
||||
/**
|
||||
* 元素阴影
|
||||
*
|
||||
@ -80,7 +82,7 @@ export interface PPTElementShadow {
|
||||
* color?: 边框颜色
|
||||
*/
|
||||
export interface PPTElementOutline {
|
||||
style?: 'dashed' | 'solid' | 'dotted'
|
||||
style?: LineStyleType
|
||||
width?: number
|
||||
color?: string
|
||||
}
|
||||
@ -390,7 +392,7 @@ export interface PPTLineElement extends Omit<PPTBaseElement, 'height' | 'rotate'
|
||||
type: 'line'
|
||||
start: [number, number]
|
||||
end: [number, number]
|
||||
style: 'solid' | 'dashed' | 'dotted'
|
||||
style: LineStyleType
|
||||
color: string
|
||||
points: [LinePoint, LinePoint]
|
||||
shadow?: PPTElementShadow
|
||||
|
@ -2,16 +2,16 @@
|
||||
<div class="line-style-panel">
|
||||
<div class="row">
|
||||
<div style="width: 40%;">线条样式:</div>
|
||||
<Select
|
||||
style="width: 60%;"
|
||||
:value="handleLineElement.style"
|
||||
@update:value="value => updateLine({ style: value as 'solid' | 'dashed' })"
|
||||
:options="[
|
||||
{ label: '实线', value: 'solid' },
|
||||
{ label: '虚线', value: 'dashed' },
|
||||
{ label: '点线', value: 'dotted' },
|
||||
]"
|
||||
/>
|
||||
<SelectCustom style="width: 60%;">
|
||||
<template #options>
|
||||
<div class="option" v-for="item in lineStyleOptions" :key="item" @click="updateLine({ style: item })">
|
||||
<SVGLine :type="item" />
|
||||
</div>
|
||||
</template>
|
||||
<template #label>
|
||||
<SVGLine :type="handleLineElement.style" />
|
||||
</template>
|
||||
</SelectCustom>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div style="width: 40%;">线条颜色:</div>
|
||||
@ -36,29 +36,29 @@
|
||||
|
||||
<div class="row">
|
||||
<div style="width: 40%;">起点样式:</div>
|
||||
<Select
|
||||
style="width: 60%;"
|
||||
:value="handleLineElement.points[0]"
|
||||
@update:value="value => updateLine({ points: [value as 'arrow' | 'dot', handleLineElement.points[1]] })"
|
||||
:options="[
|
||||
{ label: '无', value: '' },
|
||||
{ label: '箭头', value: 'arrow' },
|
||||
{ label: '圆点', value: 'dot' },
|
||||
]"
|
||||
/>
|
||||
<SelectCustom style="width: 60%;">
|
||||
<template #options>
|
||||
<div class="option" v-for="item in lineMarkerOptions" :key="item" @click="updateLine({ points: [item, handleLineElement.points[1]] })">
|
||||
<SVGLine :padding="5" :markers="[item, '']" />
|
||||
</div>
|
||||
</template>
|
||||
<template #label>
|
||||
<SVGLine :padding="5" :markers="[handleLineElement.points[0], '']" />
|
||||
</template>
|
||||
</SelectCustom>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div style="width: 40%;">终点样式:</div>
|
||||
<Select
|
||||
style="width: 60%;"
|
||||
:value="handleLineElement.points[1]"
|
||||
@update:value="value => updateLine({ points: [handleLineElement.points[0], value as 'arrow' | 'dot'] })"
|
||||
:options="[
|
||||
{ label: '无', value: '' },
|
||||
{ label: '箭头', value: 'arrow' },
|
||||
{ label: '圆点', value: 'dot' },
|
||||
]"
|
||||
/>
|
||||
<SelectCustom style="width: 60%;">
|
||||
<template #options>
|
||||
<div class="option" v-for="item in lineMarkerOptions" :key="item" @click="updateLine({ points: [handleLineElement.points[0], item] })">
|
||||
<SVGLine :padding="5" :markers="['', item]" />
|
||||
</div>
|
||||
</template>
|
||||
<template #label>
|
||||
<SVGLine :padding="5" :markers="['', handleLineElement.points[1]]" />
|
||||
</template>
|
||||
</SelectCustom>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
@ -73,19 +73,20 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from 'vue'
|
||||
import { type Ref, ref } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMainStore, useSlidesStore } from '@/store'
|
||||
import type { PPTLineElement } from '@/types/slides'
|
||||
import type { LinePoint, LineStyleType, PPTLineElement } from '@/types/slides'
|
||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||
|
||||
import ElementShadow from '../common/ElementShadow.vue'
|
||||
import SVGLine from '../common/SVGLine.vue'
|
||||
import Button from '@/components/Button.vue'
|
||||
import ColorButton from '@/components/ColorButton.vue'
|
||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||
import Divider from '@/components/Divider.vue'
|
||||
import NumberInput from '@/components/NumberInput.vue'
|
||||
import Select from '@/components/Select.vue'
|
||||
import SelectCustom from '@/components/SelectCustom.vue'
|
||||
import Popover from '@/components/Popover.vue'
|
||||
|
||||
const slidesStore = useSlidesStore()
|
||||
@ -95,6 +96,9 @@ const handleLineElement = handleElement as Ref<PPTLineElement>
|
||||
|
||||
const { addHistorySnapshot } = useHistorySnapshot()
|
||||
|
||||
const lineStyleOptions = ref<LineStyleType[]>(['solid', 'dashed', 'dotted'])
|
||||
const lineMarkerOptions = ref<LinePoint[]>(['', 'arrow', 'dot'])
|
||||
|
||||
const updateLine = (props: Partial<PPTLineElement>) => {
|
||||
if (!handleElement.value) return
|
||||
slidesStore.updateElement({ id: handleElement.value.id, props })
|
||||
@ -135,4 +139,19 @@ const updateLine = (props: Partial<PPTLineElement>) => {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.option {
|
||||
height: 32px;
|
||||
padding: 0 5px;
|
||||
border-radius: $borderRadius;
|
||||
|
||||
&:not(.selected):hover {
|
||||
background-color: rgba($color: $themeColor, $alpha: .05);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: $themeColor;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -17,16 +17,16 @@
|
||||
|
||||
<div class="row">
|
||||
<div style="width: 40%;">边框样式:</div>
|
||||
<Select
|
||||
style="width: 60%;"
|
||||
:value="outline.style || ''"
|
||||
@update:value="value => updateOutline({ style: value as 'solid' | 'dashed' | 'dotted' })"
|
||||
:options="[
|
||||
{ label: '实线边框', value: 'solid' },
|
||||
{ label: '虚线边框', value: 'dashed' },
|
||||
{ label: '点线边框', value: 'dotted' },
|
||||
]"
|
||||
/>
|
||||
<SelectCustom style="width: 60%;">
|
||||
<template #options>
|
||||
<div class="option" v-for="item in lineStyleOptions" :key="item" @click="updateOutline({ style: item })">
|
||||
<SVGLine :type="item" />
|
||||
</div>
|
||||
</template>
|
||||
<template #label>
|
||||
<SVGLine :type="outline.style" />
|
||||
</template>
|
||||
</SelectCustom>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div style="width: 40%;">边框颜色:</div>
|
||||
@ -137,11 +137,12 @@
|
||||
import { ref } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMainStore, useSlidesStore } from '@/store'
|
||||
import type { PPTElement, PPTElementOutline, TableCell } from '@/types/slides'
|
||||
import type { LineStyleType, PPTElement, PPTElementOutline, TableCell } from '@/types/slides'
|
||||
import emitter, { EmitterEvents } from '@/utils/emitter'
|
||||
import { WEB_FONTS } from '@/configs/font'
|
||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||
|
||||
import SVGLine from '../common/SVGLine.vue'
|
||||
import ColorButton from '@/components/ColorButton.vue'
|
||||
import TextColorButton from '@/components/TextColorButton.vue'
|
||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||
@ -153,6 +154,7 @@ import RadioGroup from '@/components/RadioGroup.vue'
|
||||
import NumberInput from '@/components/NumberInput.vue'
|
||||
import Select from '@/components/Select.vue'
|
||||
import SelectGroup from '@/components/SelectGroup.vue'
|
||||
import SelectCustom from '@/components/SelectCustom.vue'
|
||||
import Popover from '@/components/Popover.vue'
|
||||
|
||||
const slidesStore = useSlidesStore()
|
||||
@ -165,6 +167,7 @@ const updateElement = (id: string, props: Partial<PPTElement>) => {
|
||||
addHistorySnapshot()
|
||||
}
|
||||
|
||||
const lineStyleOptions = ref<LineStyleType[]>(['solid', 'dashed', 'dotted'])
|
||||
const fontSizeOptions = [
|
||||
'12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',
|
||||
'36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '76px',
|
||||
@ -257,4 +260,19 @@ const updateFontStyle = (command: string, value: string) => {
|
||||
.font-size-btn {
|
||||
padding: 0;
|
||||
}
|
||||
.option {
|
||||
height: 32px;
|
||||
padding: 0 5px;
|
||||
border-radius: $borderRadius;
|
||||
|
||||
&:not(.selected):hover {
|
||||
background-color: rgba($color: $themeColor, $alpha: .05);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: $themeColor;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -177,16 +177,16 @@
|
||||
<template v-if="moreThemeConfigsVisible">
|
||||
<div class="row">
|
||||
<div style="width: 40%;">边框样式:</div>
|
||||
<Select
|
||||
style="width: 60%;"
|
||||
:value="theme.outline.style || ''"
|
||||
@update:value="value => updateTheme({ outline: { ...theme.outline, style: value as 'dashed' | 'solid' | 'dotted' } })"
|
||||
:options="[
|
||||
{ label: '实线边框', value: 'solid' },
|
||||
{ label: '虚线边框', value: 'dashed' },
|
||||
{ label: '点线边框', value: 'dotted' },
|
||||
]"
|
||||
/>
|
||||
<SelectCustom style="width: 60%;">
|
||||
<template #options>
|
||||
<div class="option" v-for="item in lineStyleOptions" :key="item" @click="updateTheme({ outline: { ...theme.outline, style: item } })">
|
||||
<SVGLine :type="item" />
|
||||
</div>
|
||||
</template>
|
||||
<template #label>
|
||||
<SVGLine :type="theme.outline.style" />
|
||||
</template>
|
||||
</SelectCustom>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div style="width: 40%;">边框颜色:</div>
|
||||
@ -312,6 +312,7 @@ import type {
|
||||
SlideTheme,
|
||||
SlideBackgroundImage,
|
||||
SlideBackgroundImageSize,
|
||||
LineStyleType,
|
||||
} from '@/types/slides'
|
||||
import { PRESET_THEMES } from '@/configs/theme'
|
||||
import { WEB_FONTS } from '@/configs/font'
|
||||
@ -320,6 +321,7 @@ import useSlideTheme from '@/hooks/useSlideTheme'
|
||||
import { getImageDataURL } from '@/utils/image'
|
||||
|
||||
import ThemeStylesExtract from './ThemeStylesExtract.vue'
|
||||
import SVGLine from './common/SVGLine.vue'
|
||||
import ColorButton from '@/components/ColorButton.vue'
|
||||
import FileInput from '@/components/FileInput.vue'
|
||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||
@ -328,6 +330,7 @@ import Slider from '@/components/Slider.vue'
|
||||
import Button from '@/components/Button.vue'
|
||||
import Select from '@/components/Select.vue'
|
||||
import Popover from '@/components/Popover.vue'
|
||||
import SelectCustom from '@/components/SelectCustom.vue'
|
||||
import NumberInput from '@/components/NumberInput.vue'
|
||||
import Modal from '@/components/Modal.vue'
|
||||
import GradientBar from '@/components/GradientBar.vue'
|
||||
@ -339,6 +342,7 @@ const { slides, currentSlide, viewportRatio, theme } = storeToRefs(slidesStore)
|
||||
const moreThemeConfigsVisible = ref(false)
|
||||
const themeStylesExtractVisible = ref(false)
|
||||
const currentGradientIndex = ref(0)
|
||||
const lineStyleOptions = ref<LineStyleType[]>(['solid', 'dashed', 'dotted'])
|
||||
|
||||
const background = computed(() => {
|
||||
if (!currentSlide.value.background) {
|
||||
@ -554,4 +558,19 @@ const updateViewportRatio = (value: number) => {
|
||||
transition: opacity $transitionDelay;
|
||||
}
|
||||
}
|
||||
.option {
|
||||
height: 32px;
|
||||
padding: 0 5px;
|
||||
border-radius: $borderRadius;
|
||||
|
||||
&:not(.selected):hover {
|
||||
background-color: rgba($color: $themeColor, $alpha: .05);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: $themeColor;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -12,16 +12,16 @@
|
||||
<template v-if="hasOutline && outline">
|
||||
<div class="row">
|
||||
<div style="width: 40%;">边框样式:</div>
|
||||
<Select
|
||||
style="width: 60%;"
|
||||
:value="outline.style || ''"
|
||||
@update:value="value => updateOutline({ style: value as 'dashed' | 'solid' | 'dotted' })"
|
||||
:options="[
|
||||
{ label: '实线边框', value: 'solid' },
|
||||
{ label: '虚线边框', value: 'dashed' },
|
||||
{ label: '点线边框', value: 'dotted' },
|
||||
]"
|
||||
/>
|
||||
<SelectCustom style="width: 60%;">
|
||||
<template #options>
|
||||
<div class="option" v-for="item in lineStyleOptions" :key="item" @click="updateOutline({ style: item })">
|
||||
<SVGLine :type="item" />
|
||||
</div>
|
||||
</template>
|
||||
<template #label>
|
||||
<SVGLine :type="outline.style" />
|
||||
</template>
|
||||
</SelectCustom>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div style="width: 40%;">边框颜色:</div>
|
||||
@ -51,14 +51,15 @@
|
||||
import { ref, watch } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMainStore, useSlidesStore } from '@/store'
|
||||
import type { PPTElementOutline } from '@/types/slides'
|
||||
import type { LineStyleType, PPTElementOutline } from '@/types/slides'
|
||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||
|
||||
import SVGLine from '../common/SVGLine.vue'
|
||||
import ColorButton from '@/components/ColorButton.vue'
|
||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||
import Switch from '@/components/Switch.vue'
|
||||
import NumberInput from '@/components/NumberInput.vue'
|
||||
import Select from '@/components/Select.vue'
|
||||
import SelectCustom from '@/components/SelectCustom.vue'
|
||||
import Popover from '@/components/Popover.vue'
|
||||
|
||||
withDefaults(defineProps<{
|
||||
@ -73,6 +74,7 @@ const { handleElement } = storeToRefs(useMainStore())
|
||||
|
||||
const outline = ref<PPTElementOutline>()
|
||||
const hasOutline = ref(false)
|
||||
const lineStyleOptions = ref<LineStyleType[]>(['solid', 'dashed', 'dotted'])
|
||||
|
||||
watch(handleElement, () => {
|
||||
if (!handleElement.value) return
|
||||
@ -113,4 +115,19 @@ const toggleOutline = (checked: boolean) => {
|
||||
.switch-wrapper {
|
||||
text-align: right;
|
||||
}
|
||||
.option {
|
||||
height: 32px;
|
||||
padding: 0 5px;
|
||||
border-radius: $borderRadius;
|
||||
|
||||
&:not(.selected):hover {
|
||||
background-color: rgba($color: $themeColor, $alpha: .05);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: $themeColor;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
</style>
|
69
src/views/Editor/Toolbar/common/SVGLine.vue
Normal file
69
src/views/Editor/Toolbar/common/SVGLine.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<svg width="100%" height="100%" viewBox="0 0 100 10">
|
||||
<defs>
|
||||
<LinePointMarker
|
||||
v-if="markers && markers[0]"
|
||||
:id="id"
|
||||
position="start"
|
||||
:type="markers[0]"
|
||||
:color="color"
|
||||
:baseSize="width"
|
||||
/>
|
||||
<LinePointMarker
|
||||
v-if="markers && markers[1]"
|
||||
:id="id"
|
||||
position="end"
|
||||
:type="markers[1]"
|
||||
:color="color"
|
||||
:baseSize="width"
|
||||
/>
|
||||
</defs>
|
||||
|
||||
<line
|
||||
:x1="padding"
|
||||
:y1="5"
|
||||
:x2="100 - padding"
|
||||
:y2="5"
|
||||
:stroke="color"
|
||||
:stroke-width="width"
|
||||
:stroke-dasharray="lineDashArray"
|
||||
:marker-start="markers && markers[0] ? `url(#${id}-${markers[0]}-start)` : ''"
|
||||
:marker-end="markers && markers[1] ? `url(#${id}-${markers[1]}-end)` : ''"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { nanoid } from 'nanoid'
|
||||
import type { LinePoint, LineStyleType } from '@/types/slides'
|
||||
import LinePointMarker from '@/views/components/element/LineElement/LinePointMarker.vue'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
width?: number
|
||||
color?: string
|
||||
markers?: [LinePoint, LinePoint]
|
||||
type?: LineStyleType
|
||||
padding?: number
|
||||
}>(), {
|
||||
width: 2,
|
||||
color: '#333',
|
||||
padding: 0
|
||||
})
|
||||
|
||||
const id = ref('')
|
||||
onMounted(() => {
|
||||
id.value = nanoid()
|
||||
})
|
||||
|
||||
const lineDashArray = computed(() => {
|
||||
const size = props.width
|
||||
if (props.type === 'dashed') return size <= 8 ? `${size * 5} ${size * 2.5}` : `${size * 5} ${size * 1.5}`
|
||||
if (props.type === 'dotted') return size <= 8 ? `${size * 1.8} ${size * 1.6}` : `${size * 1.5} ${size * 1.2}`
|
||||
return '0 0'
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
@ -18,11 +18,14 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import type { LinePoint } from '@/types/slides'
|
||||
|
||||
type NonEmptyLinePoint = Exclude<LinePoint, ''>
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
position: 'start' | 'end'
|
||||
type: 'dot' | 'arrow'
|
||||
type: NonEmptyLinePoint
|
||||
baseSize: number
|
||||
color?: string
|
||||
}>()
|
||||
|
Loading…
x
Reference in New Issue
Block a user