This commit is contained in:
pipipi-pikachu 2021-01-09 10:39:06 +08:00
parent ab8d5aab63
commit 2e905e5bd8
2 changed files with 166 additions and 10 deletions

View File

@ -1,5 +1,8 @@
<template>
<div class="element-style-panel">
<div v-if="!currentPanelComponent">
请先选中要编辑的元素
</div>
<component :is="currentPanelComponent"></component>
</div>
</template>

View File

@ -1,28 +1,49 @@
<template>
<div class="multi-position-panel">
<ButtonGroup class="row">
<Button style="flex: 1;"></Button>
<Button style="flex: 1;"></Button>
<Button style="flex: 1;"></Button>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="左对齐">
<Button style="flex: 1;" @click="alignActiveElement('left')"><IconFont type="icon-align-left" /></Button>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="水平居中">
<Button style="flex: 1;" @click="alignActiveElement('horizontal')"><IconFont type="icon-align-vertical-center" /></Button>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="右对齐">
<Button style="flex: 1;" @click="alignActiveElement('right')"><IconFont type="icon-align-right" /></Button>
</Tooltip>
</ButtonGroup>
<ButtonGroup class="row">
<Button style="flex: 1;"></Button>
<Button style="flex: 1;"></Button>
<Button style="flex: 1;"></Button>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="上对齐">
<Button style="flex: 1;" @click="alignActiveElement('top')"><IconFont type="icon-align-top" /></Button>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="垂直居中">
<Button style="flex: 1;" @click="alignActiveElement('vertical')"><IconFont type="icon-align-horizontal-center" /></Button>
</Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="下对齐">
<Button style="flex: 1;" @click="alignActiveElement('bottom')"><IconFont type="icon-align-bottom" /></Button>
</Tooltip>
</ButtonGroup>
<Divider />
<ButtonGroup class="row">
<Button style="flex: 1;">组合</Button>
<Button style="flex: 1;">取消组合</Button>
<Button :disabled="!canCombine" @click="combineElements()" style="flex: 1;">组合</Button>
<Button :disabled="canCombine" @click="uncombineElements()" style="flex: 1;">取消组合</Button>
</ButtonGroup>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { Button, Divider } from 'ant-design-vue'
import { computed, defineComponent, Ref } from 'vue'
import { useStore } from 'vuex'
import { MutationTypes, State } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'
import { getElementListRange } from '@/utils/element'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import useCombineElement from '@/hooks/useCombineElement'
import { Button, Divider, Tooltip } from 'ant-design-vue'
import IconFont from '@/components/IconFont'
export default defineComponent({
name: 'multi-position-panel',
@ -30,6 +51,138 @@ export default defineComponent({
Button,
ButtonGroup: Button.Group,
Divider,
Tooltip,
IconFont,
},
setup() {
const store = useStore<State>()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
const { addHistorySnapshot } = useHistorySnapshot()
const { combineElements, uncombineElements } = useCombineElement()
const canCombine = computed(() => {
const firstGroupId = activeElementList.value[0].groupId
if(!firstGroupId) return true
const inSameGroup = activeElementList.value.every(el => (el.groupId && el.groupId) === firstGroupId)
return !inSameGroup
})
const alignActiveElement = (command: ElementAlignCommand) => {
const { minX, maxX, minY, maxY } = getElementListRange(activeElementList.value)
const elementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
//
const groupElementRangeMap = {}
for(const activeElement of activeElementList.value) {
if(activeElement.groupId && !groupElementRangeMap[activeElement.groupId]) {
const groupElements = activeElementList.value.filter(item => item.groupId === activeElement.groupId)
groupElementRangeMap[activeElement.groupId] = getElementListRange(groupElements)
}
}
if(command === ElementAlignCommands.LEFT) {
elementList.forEach(element => {
if(activeElementIdList.value.includes(element.id)) {
if(!element.groupId) element.left = minX
else {
const range = groupElementRangeMap[element.groupId]
const offset = range.minX - minX
element.left = element.left - offset
}
}
})
}
else if(command === ElementAlignCommands.RIGHT) {
elementList.forEach(element => {
if(activeElementIdList.value.includes(element.id)) {
if(!element.groupId) {
const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width
element.left = maxX - elWidth
}
else {
const range = groupElementRangeMap[element.groupId]
const offset = range.maxX - maxX
element.left = element.left - offset
}
}
})
}
else if(command === ElementAlignCommands.TOP) {
elementList.forEach(element => {
if(activeElementIdList.value.includes(element.id)) {
if(!element.groupId) element.top = minY
else {
const range = groupElementRangeMap[element.groupId]
const offset = range.minY - minY
element.top = element.top - offset
}
}
})
}
else if(command === ElementAlignCommands.BOTTOM) {
elementList.forEach(element => {
if(activeElementIdList.value.includes(element.id)) {
if(!element.groupId) {
const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height
element.top = maxY - elHeight
}
else {
const range = groupElementRangeMap[element.groupId]
const offset = range.maxY - maxY
element.top = element.top - offset
}
}
})
}
else if(command === ElementAlignCommands.HORIZONTAL) {
const horizontalCenter = (minX + maxX) / 2
elementList.forEach(element => {
if(activeElementIdList.value.includes(element.id)) {
if(!element.groupId) {
const elWidth = element.type === 'line' ? Math.max(element.start[0], element.end[0]) : element.width
element.left = horizontalCenter - elWidth / 2
}
else {
const range = groupElementRangeMap[element.groupId]
const center = (range.maxX + range.minX) / 2
const offset = center - horizontalCenter
element.left = element.left - offset
}
}
})
}
else if(command === ElementAlignCommands.VERTICAL) {
const verticalCenter = (minY + maxY) / 2
elementList.forEach(element => {
if(activeElementIdList.value.includes(element.id)) {
if(!element.groupId) {
const elHeight = element.type === 'line' ? Math.max(element.start[1], element.end[1]) : element.height
element.top = verticalCenter - elHeight / 2
}
else {
const range = groupElementRangeMap[element.groupId]
const center = (range.maxY + range.minY) / 2
const offset = center - verticalCenter
element.top = element.top - offset
}
}
})
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList })
addHistorySnapshot()
}
return {
canCombine,
combineElements,
uncombineElements,
alignActiveElement,
}
},
})
</script>