This commit is contained in:
pipipi-pikachu 2021-01-06 22:21:38 +08:00
parent f9cdbbeffc
commit f002b05cdc
12 changed files with 321 additions and 93 deletions

View File

@ -13,4 +13,7 @@
}
.ant-btn {
font-size: 13px !important;
}
.ant-select-item-option-content {
font-size: 13px !important;
}

View File

@ -7,7 +7,7 @@
font-family: '微软雅黑';
::selection {
background-color: rgba(#41464b, 0.3);
background-color: rgba(#d14424, 0.3);
color: inherit;
}

View File

@ -1,2 +1,3 @@
$themeColor: #41464b;
$themeColor: #d14424;
$textColor: #41464b;
$borderRadius: 2px;

View File

@ -1,4 +1,4 @@
const DEFAULT_COLOR = '#41464b'
const DEFAULT_COLOR = '#d14424'
export const ELEMENT_TYPE = {
'text': '文本',

View File

@ -16,7 +16,7 @@
</template>
<StarOutlined class="handler-item" />
</Popover>
<Popover trigger="click" v-model:visible="isOpenlinePool">
<Popover trigger="click" v-model:visible="isOpenLinePool">
<template #content>
<LinePool @select="line => drawLine(line)" />
</template>
@ -100,7 +100,7 @@ export default defineComponent({
}
const isOpenShapePool = ref(false)
const isOpenlinePool = ref(false)
const isOpenLinePool = ref(false)
const drawText = () => {
store.commit(MutationTypes.SET_CREATING_ELEMENT, {
type: 'text',
@ -119,7 +119,7 @@ export default defineComponent({
type: 'line',
data: line,
})
isOpenShapePool.value = false
isOpenLinePool.value = false
}
return {
@ -131,7 +131,7 @@ export default defineComponent({
undo,
insertImageElement,
isOpenShapePool,
isOpenlinePool,
isOpenLinePool,
drawText,
drawShape,
drawLine,

View File

@ -45,7 +45,7 @@ export default defineComponent({
}
.menu-item {
font-size: 13px;
color: $themeColor;
color: $textColor;
margin: 0 10px;
cursor: pointer;

View File

@ -96,76 +96,31 @@
<Divider />
<div class="row">
<div style="flex: 2;">描边样式</div>
<Select style="flex: 3;" :value="wordSpace">
<template #suffixIcon><ColumnWidthOutlined /></template>
<SelectOption v-for="item in wordSpaceOptions" :key="item" :value="item">{{item}}</SelectOption>
</Select>
</div>
<div class="row">
<div style="flex: 2;">描边颜色</div>
<Popover trigger="click">
<template #content>
<ColorPicker v-model="fill" />
</template>
<Button class="color-btn" style="flex: 3;">
<div class="color-block"></div>
<DownOutlined class="color-btn-icon" />
</Button>
</Popover>
</div>
<div class="row">
<div style="flex: 2;">描边粗细</div>
<InputNumber style="flex: 3;" />
</div>
<ElementOutline />
<Divider />
<div class="row">
<div style="flex: 2;">水平阴影</div>
<Slider :min="0" :max="1" :step="0.1" :value="opacity" style="flex: 3;" />
</div>
<div class="row">
<div style="flex: 2;">垂直阴影</div>
<Slider :min="0" :max="1" :step="0.1" :value="opacity" style="flex: 3;" />
</div>
<div class="row">
<div style="flex: 2;">模糊距离</div>
<Slider :min="0" :max="1" :step="0.1" :value="opacity" style="flex: 3;" />
</div>
<div class="row">
<div style="flex: 2;">阴影颜色</div>
<Popover trigger="click">
<template #content>
<ColorPicker v-model="fill" />
</template>
<Button class="color-btn" style="flex: 3;">
<div class="color-block"></div>
<DownOutlined class="color-btn-icon" />
</Button>
</Popover>
</div>
<ElementShadow />
<Divider />
<div class="row">
<div style="flex: 2;">透明度</div>
<Slider :min="0" :max="1" :step="0.1" :value="opacity" style="flex: 3;" />
</div>
<ElementOpacity />
</div>
</template>
<script lang="ts">
import { computed, defineComponent, onUnmounted, ref } from 'vue'
import { computed, defineComponent, onUnmounted, Ref, ref, watch } from 'vue'
import { useStore } from 'vuex'
import { State } from '@/store'
import { PPTElementOutline, PPTElementShadow } from '@/types/slides'
import { PPTTextElement } from '@/types/slides'
import emitter, { EmitterEvents } from '@/utils/emitter'
import { TextAttrs } from '@/prosemirror/utils'
import ElementOpacity from '../common/ElementOpacity.vue'
import ElementOutline from '../common/ElementOutline.vue'
import ElementShadow from '../common/ElementShadow.vue'
import ColorPicker from '@/components/ColorPicker/index.vue'
import { Select, Input, Button, Divider, Slider, Popover, InputNumber } from 'ant-design-vue'
import { Select, Input, Button, Divider, Popover } from 'ant-design-vue'
import {
FontColorsOutlined,
HighlightOutlined,
@ -181,7 +136,6 @@ import {
UnorderedListOutlined,
ColumnHeightOutlined,
ColumnWidthOutlined,
DownOutlined,
} from '@ant-design/icons-vue'
export default defineComponent({
@ -194,9 +148,7 @@ export default defineComponent({
Button,
ButtonGroup: Button.Group,
Divider,
Slider,
Popover,
InputNumber,
FontColorsOutlined,
HighlightOutlined,
BgColorsOutlined,
@ -211,17 +163,24 @@ export default defineComponent({
UnorderedListOutlined,
ColumnHeightOutlined,
ColumnWidthOutlined,
DownOutlined,
ElementOpacity,
ElementOutline,
ElementShadow,
},
setup() {
const store = useStore<State>()
const handleElement: Ref<PPTTextElement> = computed(() => store.getters.handleElement)
const fill = ref('#000')
const lineHeight = ref(1.5)
const wordSpace = ref(0)
const opacity = ref(1)
const shadow = ref<PPTElementShadow>()
const outline = ref<PPTElementOutline>()
const fill = ref<string>()
const lineHeight = ref<number>()
const wordSpace = ref<number>()
watch(handleElement, () => {
if(!handleElement.value) return
fill.value = handleElement.value.fill || '#000'
lineHeight.value = handleElement.value.lineHeight || 1.5
wordSpace.value = handleElement.value.wordSpace || 0
}, { deep: true, immediate: true })
const richTextAttrs = ref<TextAttrs>({
bold: false,
@ -260,9 +219,6 @@ export default defineComponent({
fill,
lineHeight,
wordSpace,
opacity,
shadow,
outline,
richTextAttrs,
availableFonts,
fontSizeOptions,
@ -291,19 +247,4 @@ export default defineComponent({
height: 3px;
margin-top: 1px;
}
.color-btn {
display: flex;
align-items: center;
padding: 0 !important;
}
.color-block {
width: 100px;
height: 20px;
background-color: #777;
margin: 0 8px;
}
.color-btn-icon {
font-size: 12px;
margin-top: 2px;
}
</style>

View File

@ -0,0 +1,48 @@
<template>
<div class="element-opacity">
<div class="row">
<div style="flex: 2;">不透明度</div>
<Slider :min="0" :max="1" :step="0.1" :value="opacity" style="flex: 3;" />
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, Ref, ref, watch } from 'vue'
import { useStore } from 'vuex'
import { State } from '@/store'
import { PPTElement } from '@/types/slides'
import { Slider } from 'ant-design-vue'
export default defineComponent({
name: 'element-opacity',
components: {
Slider,
},
setup() {
const store = useStore<State>()
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
const opacity = ref<number>()
watch(handleElement, () => {
if(!handleElement.value) return
opacity.value = 'opacity' in handleElement.value && handleElement.value.opacity || 1
}, { deep: true, immediate: true })
return {
opacity,
}
},
})
</script>
<style lang="scss" scoped>
.row {
width: 100%;
display: flex;
align-items: center;
margin-bottom: 10px;
}
</style>

View File

@ -0,0 +1,118 @@
<template>
<div class="element-outline">
<div class="row">
<div style="flex: 2;">启用边框</div>
<div class="switch-wrapper" style="flex: 3;">
<Switch :checked="hasOutline" @change="checked => toggleOutline(checked)" />
</div>
</div>
<template v-if="hasOutline">
<div class="row">
<div style="flex: 2;">边框样式</div>
<Select style="flex: 3;" :value="outline.style">
<SelectOption value="solid">实线边框</SelectOption>
<SelectOption value="dashed">虚线边框</SelectOption>
</Select>
</div>
<div class="row">
<div style="flex: 2;">边框颜色</div>
<Popover trigger="click">
<template #content>
<ColorPicker v-model="outline.color" />
</template>
<Button class="color-btn" style="flex: 3;">
<div class="color-block" :style="{ backgroundColor: outline.color }"></div>
<DownOutlined class="color-btn-icon" />
</Button>
</Popover>
</div>
<div class="row">
<div style="flex: 2;">边框粗细</div>
<InputNumber :value="outline.width" style="flex: 3;" />
</div>
</template>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, Ref, ref, watch } from 'vue'
import { useStore } from 'vuex'
import { State } from '@/store'
import { PPTElement, PPTElementOutline } from '@/types/slides'
import ColorPicker from '@/components/ColorPicker/index.vue'
import { Select, Button, Popover, InputNumber, Switch } from 'ant-design-vue'
import { DownOutlined } from '@ant-design/icons-vue'
export default defineComponent({
name: 'element-outline',
components: {
ColorPicker,
Select,
SelectOption: Select.Option,
Button,
Popover,
InputNumber,
Switch,
DownOutlined,
},
setup() {
const store = useStore<State>()
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
const outline = ref<PPTElementOutline>()
const hasOutline = ref(false)
watch(handleElement, () => {
if(!handleElement.value) return
outline.value = 'outline' in handleElement.value && handleElement.value.outline || undefined
hasOutline.value = !!outline.value
}, { deep: true, immediate: true })
const toggleOutline = (checked: boolean) => {
if(!checked) {
outline.value = undefined
hasOutline.value = false
}
else {
outline.value = { width: 2, color: '#000', style: 'solid' }
hasOutline.value = true
}
}
return {
outline,
hasOutline,
toggleOutline,
}
},
})
</script>
<style lang="scss" scoped>
.row {
width: 100%;
display: flex;
align-items: center;
margin-bottom: 10px;
}
.color-btn {
display: flex;
align-items: center;
padding: 0 !important;
}
.color-block {
width: 100px;
height: 20px;
background-color: #777;
margin: 0 8px;
}
.color-btn-icon {
font-size: 12px;
margin-top: 2px;
color: #bfbfbf;
}
.switch-wrapper {
text-align: right;
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<div class="element-shadow">
<div class="row">
<div style="flex: 2;">启用阴影</div>
<div class="switch-wrapper" style="flex: 3;">
<Switch :checked="hasShadow" @change="checked => toggleShadow(checked)" />
</div>
</div>
<template v-if="hasShadow">
<div class="row">
<div style="flex: 2;">水平阴影</div>
<Slider :min="1" :max="10" :step="1" :value="shadow.h" style="flex: 3;" />
</div>
<div class="row">
<div style="flex: 2;">垂直阴影</div>
<Slider :min="1" :max="10" :step="1" :value="shadow.v" style="flex: 3;" />
</div>
<div class="row">
<div style="flex: 2;">模糊距离</div>
<Slider :min="1" :max="20" :step="1" :value="shadow.blur" style="flex: 3;" />
</div>
<div class="row">
<div style="flex: 2;">阴影颜色</div>
<Popover trigger="click">
<template #content>
<ColorPicker v-model="shadow.color" />
</template>
<Button class="color-btn" style="flex: 3;">
<div class="color-block"></div>
<DownOutlined class="color-btn-icon" />
</Button>
</Popover>
</div>
</template>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, Ref, ref, watch } from 'vue'
import { useStore } from 'vuex'
import { State } from '@/store'
import { PPTElement, PPTElementShadow } from '@/types/slides'
import ColorPicker from '@/components/ColorPicker/index.vue'
import { Slider, Button, Popover, Switch } from 'ant-design-vue'
import { DownOutlined } from '@ant-design/icons-vue'
export default defineComponent({
name: 'element-shadow',
components: {
ColorPicker,
Slider,
Button,
Popover,
Switch,
DownOutlined,
},
setup() {
const store = useStore<State>()
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
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 toggleShadow = (checked: boolean) => {
if(!checked) {
shadow.value = undefined
hasShadow.value = false
}
else {
shadow.value = { h: 1, v: 1, blur: 2, color: '#000' }
hasShadow.value = true
}
}
return {
shadow,
hasShadow,
toggleShadow,
}
},
})
</script>
<style lang="scss" scoped>
.row {
width: 100%;
display: flex;
align-items: center;
margin-bottom: 10px;
}
.color-btn {
display: flex;
align-items: center;
padding: 0 !important;
}
.color-block {
width: 100px;
height: 20px;
background-color: #777;
margin: 0 8px;
}
.color-btn-icon {
font-size: 12px;
margin-top: 2px;
color: #bfbfbf;
}
.switch-wrapper {
text-align: right;
}
</style>

View File

@ -4,7 +4,7 @@ import { PPTElementOutline } from '@/types/slides'
export default (outline: Ref<PPTElementOutline | undefined>) => {
const outlineWidth = computed(() => (outline.value && outline.value.width !== undefined) ? outline.value.width : 0)
const outlineStyle = computed(() => (outline.value && outline.value.style !== undefined) ? outline.value.style : 'solid')
const outlineColor = computed(() => (outline.value && outline.value.color !== undefined) ? outline.value.color : '#41464b')
const outlineColor = computed(() => (outline.value && outline.value.color !== undefined) ? outline.value.color : '#d14424')
return {
outlineWidth,

View File

@ -12,8 +12,8 @@ module.exports = {
less: {
lessOptions: {
modifyVars: {
'primary-color': '#41464b',
'link-color': '#41464b',
'primary-color': '#d14424',
'link-color': '#d14424',
},
javascriptEnabled: true,
},