mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
173 lines
6.5 KiB
TypeScript
173 lines
6.5 KiB
TypeScript
import { storeToRefs } from 'pinia'
|
|
import { useMainStore, useSlidesStore } from '@/store'
|
|
import { PPTElement } from '@/types/slides'
|
|
import { ElementAlignCommands } from '@/types/edit'
|
|
import { getElementListRange, getRectRotatedOffset } from '@/utils/element'
|
|
import useHistorySnapshot from './useHistorySnapshot'
|
|
|
|
export default () => {
|
|
const slidesStore = useSlidesStore()
|
|
const { activeElementIdList, activeElementList } = storeToRefs(useMainStore())
|
|
const { currentSlide } = storeToRefs(slidesStore)
|
|
|
|
const { addHistorySnapshot } = useHistorySnapshot()
|
|
|
|
/**
|
|
* 对齐选中的元素
|
|
* @param command 对齐方向
|
|
*/
|
|
const alignActiveElement = (command: ElementAlignCommands) => {
|
|
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) {
|
|
if ('rotate' in element && element.rotate) {
|
|
const { offsetX } = getRectRotatedOffset({
|
|
left: element.left,
|
|
top: element.top,
|
|
width: element.width,
|
|
height: element.height,
|
|
rotate: element.rotate,
|
|
})
|
|
element.left = minX - offsetX
|
|
}
|
|
else 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
|
|
if ('rotate' in element && element.rotate) {
|
|
const { offsetX } = getRectRotatedOffset({
|
|
left: element.left,
|
|
top: element.top,
|
|
width: element.width,
|
|
height: element.height,
|
|
rotate: element.rotate,
|
|
})
|
|
element.left = maxX - elWidth + offsetX
|
|
}
|
|
else 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) {
|
|
if ('rotate' in element && element.rotate) {
|
|
const { offsetY } = getRectRotatedOffset({
|
|
left: element.left,
|
|
top: element.top,
|
|
width: element.width,
|
|
height: element.height,
|
|
rotate: element.rotate,
|
|
})
|
|
element.top = minY - offsetY
|
|
}
|
|
else 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
|
|
if ('rotate' in element && element.rotate) {
|
|
const { offsetY } = getRectRotatedOffset({
|
|
left: element.left,
|
|
top: element.top,
|
|
width: element.width,
|
|
height: element.height,
|
|
rotate: element.rotate,
|
|
})
|
|
element.top = maxY - elHeight + offsetY
|
|
}
|
|
else 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
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
slidesStore.updateSlide({ elements: elementList })
|
|
addHistorySnapshot()
|
|
}
|
|
|
|
return {
|
|
alignActiveElement,
|
|
}
|
|
} |