feat: 形状支持缩放重新计算路径

This commit is contained in:
pipipi-pikachu 2022-02-27 16:22:26 +08:00
parent 47234085da
commit 14c6965153
4 changed files with 81 additions and 9 deletions

View File

@ -1,7 +1,10 @@
import { ShapePathFormulasKeys } from '@/types/slides'
export interface ShapePoolItem {
viewBox: [number, number];
path: string;
special?: boolean;
pathFormula?: ShapePathFormulasKeys;
}
interface ShapeListItem {
@ -9,6 +12,37 @@ interface ShapeListItem {
children: ShapePoolItem[];
}
export const SHAPE_PATH_FORMULAS = {
[ShapePathFormulasKeys.ROUND_RECT]: (width: number, height: number) => {
const radius = Math.min(width, height) / 8
return `M ${radius} 0 L ${width - radius} 0 Q ${width} 0 ${width} ${radius} L ${width} ${height - radius} Q ${width} ${height} ${width - radius} ${height} L ${radius} ${height} Q 0 ${height} 0 ${height - radius} L 0 ${radius} Q 0 0 ${radius} 0 Z`
},
[ShapePathFormulasKeys.CUT_RECT_DIAGONAL]: (width: number, height: number) => {
const radius = Math.min(width, height) / 5
return `M 0 ${height - radius} L 0 0 L ${width - radius} 0 L ${width} ${radius} L ${width} ${height} L ${radius} ${height} Z`
},
[ShapePathFormulasKeys.CUT_RECT_SINGLE]: (width: number, height: number) => {
const radius = Math.min(width, height) / 5
return `M 0 ${height} L 0 0 L ${width - radius} 0 L ${width} ${radius} L ${width} ${height} Z`
},
[ShapePathFormulasKeys.CUT_RECT_SAMESIDE]: (width: number, height: number) => {
const radius = Math.min(width, height) / 5
return `M 0 ${radius} L ${radius} 0 L ${width - radius} 0 L ${width} ${radius} L ${width} ${height} L 0 ${height} Z`
},
[ShapePathFormulasKeys.ROUND_RECT_DIAGONAL]: (width: number, height: number) => {
const radius = Math.min(width, height) / 8
return `M 0 0 L ${width - radius} 0 Q ${width} 0 ${width} ${radius} L ${width} ${height} L ${radius} ${height} Q 0 ${height} 0 ${height - radius} L 0 0 Z`
},
[ShapePathFormulasKeys.ROUND_RECT_SINGLE]: (width: number, height: number) => {
const radius = Math.min(width, height) / 8
return `M 0 0 L ${width - radius} 0 Q ${width} 0 ${width} ${radius} L ${width} ${height} L 0 ${height} L 0 0 Z`
},
[ShapePathFormulasKeys.ROUND_RECT_SAMESIDE]: (width: number, height: number) => {
const radius = Math.min(width, height) / 8
return `M 0 ${radius} Q 0 0 ${radius} 0 L ${width - radius} 0 Q ${width} 0 ${width} ${radius} L ${width} ${height} L 0 ${height} Z`
},
}
export const SHAPE_LIST: ShapeListItem[] = [
{
type: '矩形',
@ -19,31 +53,38 @@ export const SHAPE_LIST: ShapeListItem[] = [
},
{
viewBox: [200, 200],
path: 'M 20 0 L 180 0 Q 200 0 200 20 L 200 180 Q 200 200 180 200 L 20 200 Q 0 200 0 180 L 0 20 Q 0 0 20 0 Z'
path: 'M 50 0 L 150 0 Q 200 0 200 50 L 200 150 Q 200 200 150 200 L 50 200 Q 0 200 0 150 L 0 50 Q 0 0 50 0 Z',
pathFormula: ShapePathFormulasKeys.ROUND_RECT,
},
{
viewBox: [200, 200],
path: 'M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 L 0 150 Z'
path: 'M 0 150 L 0 0 L 150 0 L 200 50 L 200 200 L 50 200 Z',
pathFormula: ShapePathFormulasKeys.CUT_RECT_DIAGONAL,
},
{
viewBox: [200, 200],
path: 'M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 L 0 200'
path: 'M 0 200 L 0 0 L 150 0 L 200 50 L 200 200 Z',
pathFormula: ShapePathFormulasKeys.CUT_RECT_SINGLE,
},
{
viewBox: [200, 200],
path: 'M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 L 0 50 Z'
path: 'M 0 50 L 50 0 L 150 0 L 200 50 L 200 200 L 0 200 Z',
pathFormula: ShapePathFormulasKeys.CUT_RECT_SAMESIDE,
},
{
viewBox: [200, 200],
path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 60 200 Q 0 200 0 140 L 0 0 Z'
path: 'M 0 0 L 150 0 Q 200 0 200 50 L 200 200 L 50 200 Q 0 200 0 150 L 0 0 Z',
pathFormula: ShapePathFormulasKeys.ROUND_RECT_DIAGONAL,
},
{
viewBox: [200, 200],
path: 'M 0 0 L 140 0 Q 200 0 200 60 L 200 200 L 0 200 L 0 0 Z'
path: 'M 0 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 0 Z',
pathFormula: ShapePathFormulasKeys.ROUND_RECT_SINGLE,
},
{
viewBox: [200, 200],
path: 'M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 L 0 50 Z'
path: 'M 0 50 Q 0 0 50 0 L 150 0 Q 200 0 200 50 L 200 200 L 0 200 Z',
pathFormula: ShapePathFormulasKeys.ROUND_RECT_SAMESIDE,
},
]
},

View File

@ -4,7 +4,7 @@ import { createRandomCode } from '@/utils/common'
import { getImageSize } from '@/utils/image'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import { PPTLineElement, ChartType, PPTElement, TableCell, TableCellStyle, PPTShapeElement } from '@/types/slides'
import { ShapePoolItem } from '@/configs/shapes'
import { ShapePoolItem, SHAPE_PATH_FORMULAS } from '@/configs/shapes'
import { LinePoolItem } from '@/configs/lines'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -195,6 +195,11 @@ export default () => {
rotate: 0,
}
if (data.special) newElement.special = true
if (data.pathFormula) {
newElement.pathFormula = data.pathFormula
newElement.viewBox = [width, height]
newElement.path = SHAPE_PATH_FORMULAS[data.pathFormula](width, height)
}
createElement(newElement)
}

View File

@ -1,5 +1,15 @@
import { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'
export const enum ShapePathFormulasKeys {
ROUND_RECT = 'roundRect',
ROUND_RECT_DIAGONAL = 'roundRectDiagonal',
ROUND_RECT_SINGLE = 'roundRectSingle',
ROUND_RECT_SAMESIDE = 'roundRectSameSide',
CUT_RECT_DIAGONAL = 'cutRectDiagonal',
CUT_RECT_SINGLE = 'cutRectSingle',
CUT_RECT_SAMESIDE = 'cutRectSameSide',
}
export const enum ElementTypes {
TEXT = 'text',
IMAGE = 'image',
@ -277,6 +287,10 @@ export interface ShapeText {
* special?: 特殊形状使 L Q C A
*
* text?: 形状内文本
*
* pathFormula?: 形状路径计算公式
* viewBox viewBox path
* viewBox path
*/
export interface PPTShapeElement extends PPTBaseElement {
type: 'shape';
@ -292,6 +306,7 @@ export interface PPTShapeElement extends PPTBaseElement {
shadow?: PPTElementShadow;
special?: boolean;
text?: ShapeText;
pathFormula?: ShapePathFormulasKeys;
}

View File

@ -5,6 +5,7 @@ import { PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/
import { OperateResizeHandlers, OperateResizeHandler, AlignmentLineProps, MultiSelectRange } from '@/types/edit'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import { MIN_SIZE } from '@/configs/element'
import { SHAPE_PATH_FORMULAS } from '@/configs/shapes'
import { AlignLine, uniqAlignLines } from '@/utils/element'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -393,7 +394,17 @@ export default (
}
}
elementList.value = elementList.value.map(el => element.id === el.id ? { ...el, left, top, width, height } : el)
elementList.value = elementList.value.map(el => {
if (element.id !== el.id) return el
if (el.type === 'shape' && 'pathFormula' in el && el.pathFormula) {
return {
...el, left, top, width, height,
viewBox: [width, height],
path: SHAPE_PATH_FORMULAS[el.pathFormula](width, height),
}
}
return { ...el, left, top, width, height }
})
}
document.onmouseup = e => {