| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import { PPTElement } from '@/types/slides'
- // 获取矩形旋转后在画布中的位置范围
- interface RotatedElementData {
- left: number;
- top: number;
- width: number;
- height: number;
- rotate: number;
- }
- export const getRectRotatedRange = (element: RotatedElementData) => {
- const { left, top, width, height, rotate = 0 } = element
- const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2
- const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI
- const tlbraRadian = (180 - rotate - auxiliaryAngle) * Math.PI / 180
- const trblaRadian = (auxiliaryAngle - rotate) * Math.PI / 180
- const halfWidth = width / 2
- const halfHeight = height / 2
- const middleLeft = left + halfWidth
- const middleTop = top + halfHeight
- const xAxis = [
- middleLeft + radius * Math.cos(tlbraRadian),
- middleLeft + radius * Math.cos(trblaRadian),
- middleLeft - radius * Math.cos(tlbraRadian),
- middleLeft - radius * Math.cos(trblaRadian),
- ]
- const yAxis = [
- middleTop - radius * Math.sin(tlbraRadian),
- middleTop - radius * Math.sin(trblaRadian),
- middleTop + radius * Math.sin(tlbraRadian),
- middleTop + radius * Math.sin(trblaRadian),
- ]
- return {
- xRange: [Math.min(...xAxis), Math.max(...xAxis)],
- yRange: [Math.min(...yAxis), Math.max(...yAxis)],
- }
- }
- // 获取元素在画布中的位置范围
- export const getElementRange = (element: PPTElement) => {
- let minX, maxX, minY, maxY
- if (element.type === 'line') {
- minX = element.left
- maxX = element.left + Math.max(element.start[0], element.end[0])
- minY = element.top
- maxY = element.top + Math.max(element.start[1], element.end[1])
- }
- else if ('rotate' in element && element.rotate) {
- const { left, top, width, height, rotate } = element
- const { xRange, yRange } = getRectRotatedRange({ left, top, width, height, rotate })
- minX = xRange[0]
- maxX = xRange[1]
- minY = yRange[0]
- maxY = yRange[1]
- }
- else {
- minX = element.left
- maxX = element.left + element.width
- minY = element.top
- maxY = element.top + element.height
- }
- return { minX, maxX, minY, maxY }
- }
- // 获取元素集合在画布中的位置范围
- export const getElementListRange = (elementList: PPTElement[]) => {
- const leftValues: number[] = []
- const topValues: number[] = []
- const rightValues: number[] = []
- const bottomValues: number[] = []
- elementList.forEach(element => {
- const { minX, maxX, minY, maxY } = getElementRange(element)
- leftValues.push(minX)
- topValues.push(minY)
- rightValues.push(maxX)
- bottomValues.push(maxY)
- })
- const minX = Math.min(...leftValues)
- const maxX = Math.max(...rightValues)
- const minY = Math.min(...topValues)
- const maxY = Math.max(...bottomValues)
- return { minX, maxX, minY, maxY }
- }
- export interface AlignLine {
- value: number;
- range: [number, number];
- }
- // 对齐参考线去重,对于相同位置的多条参考线,取长度范围的最小值和最大值,并基于此范围将多条参考线合并为一条
- export const uniqAlignLines = (lines: AlignLine[]) => {
- const uniqLines: AlignLine[] = []
- lines.forEach(line => {
- const index = uniqLines.findIndex(_line => _line.value === line.value)
- if (index === -1) uniqLines.push(line)
- else {
- const uniqLine = uniqLines[index]
- const rangeMin = Math.min(uniqLine.range[0], line.range[0])
- const rangeMax = Math.max(uniqLine.range[1], line.range[1])
- const range: [number, number] = [rangeMin, rangeMax]
- const _line = { value: line.value, range }
- uniqLines[index] = _line
- }
- })
- return uniqLines
- }
|