mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
update
This commit is contained in:
parent
ab8d5aab63
commit
2e905e5bd8
@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="element-style-panel">
|
<div class="element-style-panel">
|
||||||
|
<div v-if="!currentPanelComponent">
|
||||||
|
请先选中要编辑的元素
|
||||||
|
</div>
|
||||||
<component :is="currentPanelComponent"></component>
|
<component :is="currentPanelComponent"></component>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,28 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="multi-position-panel">
|
<div class="multi-position-panel">
|
||||||
<ButtonGroup class="row">
|
<ButtonGroup class="row">
|
||||||
<Button style="flex: 1;">左</Button>
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="左对齐">
|
||||||
<Button style="flex: 1;">中</Button>
|
<Button style="flex: 1;" @click="alignActiveElement('left')"><IconFont type="icon-align-left" /></Button>
|
||||||
<Button style="flex: 1;">右</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>
|
||||||
<ButtonGroup class="row">
|
<ButtonGroup class="row">
|
||||||
<Button style="flex: 1;">上</Button>
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="上对齐">
|
||||||
<Button style="flex: 1;">中</Button>
|
<Button style="flex: 1;" @click="alignActiveElement('top')"><IconFont type="icon-align-top" /></Button>
|
||||||
<Button style="flex: 1;">下</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>
|
</ButtonGroup>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<ButtonGroup class="row">
|
<ButtonGroup class="row">
|
||||||
<Button style="flex: 1;">组合</Button>
|
<Button :disabled="!canCombine" @click="combineElements()" style="flex: 1;">组合</Button>
|
||||||
<Button style="flex: 1;">取消组合</Button>
|
<Button :disabled="canCombine" @click="uncombineElements()" style="flex: 1;">取消组合</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue'
|
import { computed, defineComponent, Ref } from 'vue'
|
||||||
import { Button, Divider } from 'ant-design-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({
|
export default defineComponent({
|
||||||
name: 'multi-position-panel',
|
name: 'multi-position-panel',
|
||||||
@ -30,6 +51,138 @@ export default defineComponent({
|
|||||||
Button,
|
Button,
|
||||||
ButtonGroup: Button.Group,
|
ButtonGroup: Button.Group,
|
||||||
Divider,
|
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>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user