| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- import { storeToRefs } from 'pinia'
- import { useMainStore, useSlidesStore } from '@/store'
- import type { PPTElement } from '@/types/slides'
- import { ElementAlignCommands } from '@/types/edit'
- import { getElementListRange, getRectRotatedOffset } from '@/utils/element'
- import useHistorySnapshot from './useHistorySnapshot'
- interface RangeMap {
- [id: string]: ReturnType<typeof getElementListRange>
- }
- 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: RangeMap = {}
- 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,
- }
- }
|