feat: 形状编辑支持多个控制点(#228)

This commit is contained in:
zxc 2024-07-21 22:55:55 +08:00
parent dad2295f04
commit f2b25336f4
11 changed files with 861 additions and 698 deletions

View File

@ -6,8 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="基于 Vue3.x + TypeScript 的在线演示文稿(幻灯片)应用,还原了大部分 Office PowerPoint 常用功能实现在线PPT的编辑、演示。支持导出PPT文件。" />
<meta name="keywords" content="ppt,powerpoint,office powerpoint,在线ppt,幻灯片,演示文稿,ppt在线制作,Vue3,TypeScript" />
<meta name="description" content="PPTist基于 Vue3.x + TypeScript 的在线演示文稿(幻灯片)应用,还原了大部分 Office PowerPoint 常用功能实现在线PPT的编辑、演示。支持导出PPT文件。" />
<meta name="keywords" content="pptist,ppt,powerpoint,office powerpoint,在线ppt,幻灯片,演示文稿,ppt在线制作,Vue3,TypeScript" />
<title>PPTist - 在线演示文稿</title>
<style>

1203
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@
"number-precision": "^1.6.0",
"pinia": "^2.1.7",
"pptxgenjs": "^3.12.0",
"pptxtojson": "^0.1.4",
"pptxtojson": "^0.1.7",
"prosemirror-commands": "^1.5.2",
"prosemirror-dropcursor": "^1.8.1",
"prosemirror-gapcursor": "^1.3.2",
@ -44,7 +44,7 @@
"svg-pathdata": "^6.0.3",
"tinycolor2": "^1.6.0",
"tippy.js": "^6.3.7",
"vue": "^3.3.11",
"vue": "^3.4.33",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
@ -67,7 +67,7 @@
"npm-run-all2": "^6.1.1",
"sass": "^1.69.6",
"typescript": "~5.3.0",
"vite": "^5.0.10",
"vue-tsc": "^1.8.25"
"vite": "^5.3.4",
"vue-tsc": "^2.0.26"
}
}

View File

@ -19,206 +19,226 @@ interface ShapeListItem {
children: ShapePoolItem[]
}
export const SHAPE_PATH_FORMULAS = {
export interface ShapePathFormula {
editable?: boolean
defaultValue?: number[]
range?: [number, number][]
relative?: string[]
getBaseSize?: ((width: number, height: number) => number)[]
formula: (width: number, height: number, values?: number[]) => string
}
export const SHAPE_PATH_FORMULAS: {
[key: string]: ShapePathFormula
} = {
[ShapePathFormulasKeys.ROUND_RECT]: {
editable: true,
defaultValue: 0.125,
range: [0, 0.5],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.125],
range: [[0, 0.5]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
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]: {
editable: true,
defaultValue: 0.2,
range: [0, 0.9],
relative: 'right',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.2],
range: [[0, 0.9]],
relative: ['right'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
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]: {
editable: true,
defaultValue: 0.2,
range: [0, 0.9],
relative: 'right',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.2],
range: [[0, 0.9]],
relative: ['right'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
return `M 0 ${height} L 0 0 L ${width - radius} 0 L ${width} ${radius} L ${width} ${height} Z`
}
},
[ShapePathFormulasKeys.CUT_RECT_SAMESIDE]: {
editable: true,
defaultValue: 0.2,
range: [0, 0.5],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.2],
range: [[0, 0.5]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
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]: {
editable: true,
defaultValue: 0.125,
range: [0, 1],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.125],
range: [[0, 1]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
return `M ${radius} 0 L ${width} 0 L ${width} ${height - radius} Q ${width} ${height} ${width - radius} ${height} L 0 ${height} L 0 ${radius} Q 0 0 ${radius} 0 Z`
}
},
[ShapePathFormulasKeys.ROUND_RECT_SINGLE]: {
editable: true,
defaultValue: 0.125,
range: [0, 1],
relative: 'right',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.125],
range: [[0, 1]],
relative: ['right'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
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]: {
editable: true,
defaultValue: 0.125,
range: [0, 0.5],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.125],
range: [[0, 0.5]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
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`
}
},
[ShapePathFormulasKeys.CUT_ROUND_RECT]: {
editable: true,
defaultValue: 0.125,
range: [0, 0.5],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const radius = Math.min(width, height) * value
defaultValue: [0.125],
range: [[0, 0.5]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const radius = Math.min(width, height) * values![0]
return `M ${radius} 0 L ${width - radius} 0 L ${width} ${radius} L ${width} ${height} L 0 ${height} L 0 ${radius} Q 0 0 ${radius} 0 Z`
}
},
[ShapePathFormulasKeys.MESSAGE]: {
formula: (width: number, height: number) => {
editable: true,
range: [[0, 0.8], [0.1, 0.3]],
defaultValue: [0.3, 0.2],
relative: ['left_bottom', 'bottom'],
getBaseSize: [
width => width,
(width, height) => height,
],
formula: (width, height, values) => {
const point = width * values![0]
const arrowWidth = width * 0.2
const arrowheight = height * 0.2
return `M 0 0 L ${width} 0 L ${width} ${height - arrowheight} L ${width / 2} ${height - arrowheight} L ${width / 2 - arrowWidth} ${height} L ${width / 2 - arrowWidth} ${height - arrowheight} L 0 ${height - arrowheight} Z`
const arrowheight = height * values![1]
return `M 0 0 L ${width} 0 L ${width} ${height - arrowheight} L ${point + arrowWidth} ${height - arrowheight} L ${point} ${height} L ${point} ${height - arrowheight} L 0 ${height - arrowheight} Z`
}
},
[ShapePathFormulasKeys.ROUND_MESSAGE]: {
formula: (width: number, height: number) => {
formula: (width, height) => {
const radius = Math.min(width, height) * 0.125
const arrowWidth = width * 0.2
const arrowheight = height * 0.2
const arrowWidth = Math.min(width, height) * 0.2
const arrowheight = Math.min(width, height) * 0.2
return `M 0 ${radius} Q 0 0 ${radius} 0 L ${width - radius} 0 Q ${width} 0 ${width} ${radius} L ${width} ${height - radius - arrowheight} Q ${width} ${height - arrowheight} ${width - radius} ${height - arrowheight} L ${width / 2} ${height - arrowheight} L ${width / 2 - arrowWidth} ${height} L ${width / 2 - arrowWidth} ${height - arrowheight} L ${radius} ${height - arrowheight} Q 0 ${height - arrowheight} 0 ${height - radius - arrowheight} L 0 ${radius} Z`
}
},
[ShapePathFormulasKeys.L]: {
editable: true,
defaultValue: 0.25,
range: [0.1, 0.9],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const lineWidth = Math.min(width, height) * value
defaultValue: [0.25],
range: [[0.1, 0.9]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const lineWidth = Math.min(width, height) * values![0]
return `M 0 0 L 0 ${height} L ${width} ${height} L ${width} ${height - lineWidth} L ${lineWidth} ${height - lineWidth} L ${lineWidth} 0 Z`
}
},
[ShapePathFormulasKeys.RING_RECT]: {
editable: true,
defaultValue: 0.25,
range: [0.1, 0.45],
relative: 'left',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const lineWidth = Math.min(width, height) * value
defaultValue: [0.25],
range: [[0.1, 0.45]],
relative: ['left'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const lineWidth = Math.min(width, height) * values![0]
return `M 0 0 ${width} 0 ${width} ${height} L 0 ${height} L 0 0 Z M ${lineWidth} ${lineWidth} L ${lineWidth} ${height - lineWidth} L ${width - lineWidth} ${height - lineWidth} L ${width - lineWidth} ${lineWidth} Z`
}
},
[ShapePathFormulasKeys.PLUS]: {
editable: true,
defaultValue: 0.25,
range: [0.1, 0.9],
relative: 'center',
getBaseSize: (width: number, height: number) => Math.min(width, height),
formula: (width: number, height: number, value: number) => {
const lineWidth = Math.min(width, height) * value
defaultValue: [0.25],
range: [[0.1, 0.9]],
relative: ['center'],
getBaseSize: [(width, height) => Math.min(width, height)],
formula: (width, height, values) => {
const lineWidth = Math.min(width, height) * values![0]
return `M ${width / 2 - lineWidth / 2} 0 L ${width / 2 - lineWidth / 2} ${height / 2 - lineWidth / 2} L 0 ${height / 2 - lineWidth / 2} L 0 ${height / 2 + lineWidth / 2} L ${width / 2 - lineWidth / 2} ${height / 2 + lineWidth / 2} L ${width / 2 - lineWidth / 2} ${height} L ${width / 2 + lineWidth / 2} ${height} L ${width / 2 + lineWidth / 2} ${height / 2 + lineWidth / 2} L ${width} ${height / 2 + lineWidth / 2} L ${width} ${height / 2 - lineWidth / 2} L ${width / 2 + lineWidth / 2} ${height / 2 - lineWidth / 2} L ${width / 2 + lineWidth / 2} 0 Z`
}
},
[ShapePathFormulasKeys.TRIANGLE]: {
editable: true,
defaultValue: 0.5,
range: [0, 1],
relative: 'left',
getBaseSize: (width: number) => width,
formula: (width: number, height: number, value: number) => {
const vertex = width * value
defaultValue: [0.5],
range: [[0, 1]],
relative: ['left'],
getBaseSize: [width => width],
formula: (width, height, values) => {
const vertex = width * values![0]
return `M ${vertex} 0 L 0 ${height} L ${width} ${height} Z`
}
},
[ShapePathFormulasKeys.PARALLELOGRAM_LEFT]: {
editable: true,
defaultValue: 0.25,
range: [0, 0.9],
relative: 'left',
getBaseSize: (width: number) => width,
formula: (width: number, height: number, value: number) => {
const point = width * value
defaultValue: [0.25],
range: [[0, 0.9]],
relative: ['left'],
getBaseSize: [width => width],
formula: (width, height, values) => {
const point = width * values![0]
return `M ${point} 0 L ${width} 0 L ${width - point} ${height} L 0 ${height} Z`
}
},
[ShapePathFormulasKeys.PARALLELOGRAM_RIGHT]: {
editable: true,
defaultValue: 0.25,
range: [0, 0.9],
relative: 'right',
getBaseSize: (width: number) => width,
formula: (width: number, height: number, value: number) => {
const point = width * value
defaultValue: [0.25],
range: [[0, 0.9]],
relative: ['right'],
getBaseSize: [width => width],
formula: (width, height, values) => {
const point = width * values![0]
return `M 0 0 L ${width - point} 0 L ${width} ${height} L ${point} ${height} Z`
}
},
[ShapePathFormulasKeys.TRAPEZOID]: {
editable: true,
defaultValue: 0.25,
range: [0, 0.5],
relative: 'left',
getBaseSize: (width: number) => width,
formula: (width: number, height: number, value: number) => {
const point = width * value
defaultValue: [0.25],
range: [[0, 0.5]],
relative: ['left'],
getBaseSize: [width => width],
formula: (width, height, values) => {
const point = width * values![0]
return `M ${point} 0 L ${width - point} 0 L ${width} ${height} L 0 ${height} Z`
}
},
[ShapePathFormulasKeys.BULLET]: {
editable: true,
defaultValue: 0.2,
range: [0, 1],
relative: 'top',
getBaseSize: (width: number, height: number) => height,
formula: (width: number, height: number, value: number) => {
const point = height * value
defaultValue: [0.2],
range: [[0, 1]],
relative: ['top'],
getBaseSize: [(width, height) => height],
formula: (width, height, values) => {
const point = height * values![0]
return `M ${width / 2} 0 L 0 ${point} L 0 ${height} L ${width} ${height} L ${width} ${point} Z`
}
},
[ShapePathFormulasKeys.INDICATOR]: {
editable: true,
defaultValue: 0.2,
range: [0, 0.9],
relative: 'right',
getBaseSize: (width: number) => width,
formula: (width: number, height: number, value: number) => {
const point = width * value
defaultValue: [0.2],
range: [[0, 0.9]],
relative: ['right'],
getBaseSize: [width => width],
formula: (width, height, values) => {
const point = width * values![0]
return `M ${width} ${height / 2} L ${width - point} 0 L 0 0 L ${point} ${height / 2} L 0 ${height} L ${width - point} ${height} Z`
}
},

View File

@ -235,9 +235,9 @@ export default () => {
newElement.viewBox = [width, height]
const pathFormula = SHAPE_PATH_FORMULAS[data.pathFormula]
if ('editable' in pathFormula) {
newElement.path = pathFormula.formula(width, height, pathFormula.defaultValue)
newElement.keypoint = pathFormula.defaultValue
if ('editable' in pathFormula && pathFormula.editable) {
newElement.path = pathFormula.formula(width, height, pathFormula.defaultValue!)
newElement.keypoints = pathFormula.defaultValue
}
else newElement.path = pathFormula.formula(width, height)
}

View File

@ -319,7 +319,7 @@ export interface ShapeText {
* viewBox viewBox path
* viewBox path
*
* keypoint?: 关键点位置百分比
* keypoints?: 关键点位置百分比
*/
export interface PPTShapeElement extends PPTBaseElement {
type: 'shape'
@ -336,7 +336,7 @@ export interface PPTShapeElement extends PPTBaseElement {
special?: boolean
text?: ShapeText
pathFormula?: ShapePathFormulasKeys
keypoint?: number
keypoints?: number[]
}

View File

@ -24,9 +24,10 @@
/>
<div
class="operate-keypoint-handler"
v-if="elementInfo.keypoint !== undefined"
:style="keypointStyle"
@mousedown.stop="$event => moveShapeKeypoint($event, elementInfo)"
v-for="(keypoint, index) in keypoints"
:key="index"
:style="keypoint.styles"
@mousedown.stop="$event => moveShapeKeypoint($event, elementInfo, index)"
></div>
</template>
</div>
@ -39,7 +40,7 @@ export default {
</script>
<script lang="ts" setup>
import { computed } from 'vue'
import { computed, type CSSProperties } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import type { PPTShapeElement } from '@/types/slides'
@ -56,7 +57,7 @@ const props = defineProps<{
handlerVisible: boolean
rotateElement: (e: MouseEvent, element: PPTShapeElement) => void
scaleElement: (e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandlers) => void
moveShapeKeypoint: (e: MouseEvent, element: PPTShapeElement) => void
moveShapeKeypoint: (e: MouseEvent, element: PPTShapeElement, index: number) => void
}>()
const { canvasScale } = storeToRefs(useMainStore())
@ -65,19 +66,31 @@ const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)
const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)
const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)
const keypointStyle = computed(() => {
if (!props.elementInfo.pathFormula || props.elementInfo.keypoint === undefined) return {}
const keypoints = computed(() => {
if (!props.elementInfo.pathFormula || props.elementInfo.keypoints === undefined) return []
const pathFormula = SHAPE_PATH_FORMULAS[props.elementInfo.pathFormula]
if ('editable' in pathFormula) {
const keypointPos = pathFormula.getBaseSize(props.elementInfo.width, props.elementInfo.height) * props.elementInfo.keypoint
if (pathFormula.relative === 'left') return { left: keypointPos * canvasScale.value + 'px' }
if (pathFormula.relative === 'right') return { left: (props.elementInfo.width - keypointPos) * canvasScale.value + 'px' }
if (pathFormula.relative === 'center') return { left: (props.elementInfo.width - keypointPos) / 2 * canvasScale.value + 'px' }
if (pathFormula.relative === 'top') return { top: keypointPos * canvasScale.value + 'px' }
if (pathFormula.relative === 'bottom') return { top: (props.elementInfo.height - keypointPos) * canvasScale.value + 'px' }
}
return {}
return props.elementInfo.keypoints.map((keypoint, index) => {
const getBaseSize = pathFormula.getBaseSize![index]
const relative = pathFormula.relative![index]
const keypointPos = getBaseSize(props.elementInfo.width, props.elementInfo.height) * keypoint
let styles: CSSProperties = {}
if (relative === 'left') styles = { left: keypointPos * canvasScale.value + 'px' }
else if (relative === 'right') styles = { left: (props.elementInfo.width - keypointPos) * canvasScale.value + 'px' }
else if (relative === 'center') styles = { left: (props.elementInfo.width - keypointPos) / 2 * canvasScale.value + 'px' }
else if (relative === 'top') styles = { top: keypointPos * canvasScale.value + 'px' }
else if (relative === 'bottom') styles = { top: (props.elementInfo.height - keypointPos) * canvasScale.value + 'px' }
else if (relative === 'left_bottom') styles = { left: keypointPos * canvasScale.value + 'px', top: props.elementInfo.height * canvasScale.value + 'px' }
else if (relative === 'right_bottom') styles = { left: (props.elementInfo.width - keypointPos) * canvasScale.value + 'px', top: props.elementInfo.height * canvasScale.value + 'px' }
else if (relative === 'top_right') styles = { left: props.elementInfo.width * canvasScale.value + 'px', top: keypointPos * canvasScale.value + 'px' }
else if (relative === 'bottom_right') styles = { left: props.elementInfo.width * canvasScale.value + 'px', top: (props.elementInfo.height - keypointPos) * canvasScale.value + 'px' }
return {
keypoint,
styles,
}
})
})
</script>

View File

@ -69,7 +69,7 @@ const props = defineProps<{
rotateElement: (e: MouseEvent, element: Exclude<PPTElement, PPTChartElement | PPTLineElement | PPTVideoElement | PPTAudioElement>) => void
scaleElement: (e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: OperateResizeHandlers) => void
dragLineElement: (e: MouseEvent, element: PPTLineElement, command: OperateLineHandlers) => void
moveShapeKeypoint: (e: MouseEvent, element: PPTShapeElement) => void
moveShapeKeypoint: (e: MouseEvent, element: PPTShapeElement, index: number) => void
openLinkDialog: () => void
}>()

View File

@ -20,7 +20,7 @@ export default (
const { addHistorySnapshot } = useHistorySnapshot()
const moveShapeKeypoint = (e: MouseEvent | TouchEvent, element: PPTShapeElement) => {
const moveShapeKeypoint = (e: MouseEvent | TouchEvent, element: PPTShapeElement, index = 0) => {
const isTouchEvent = !(e instanceof MouseEvent)
if (isTouchEvent && (!e.changedTouches || !e.changedTouches[0])) return
@ -29,13 +29,19 @@ export default (
const startPageX = isTouchEvent ? e.changedTouches[0].pageX : e.pageX
const startPageY = isTouchEvent ? e.changedTouches[0].pageY : e.pageY
const originKeypoints = element.keypoints!
const pathFormula = SHAPE_PATH_FORMULAS[element.pathFormula!]
let shapePathData: ShapePathData | null = null
if ('editable' in pathFormula) {
const baseSize = pathFormula.getBaseSize(element.width, element.height)
const originPos = baseSize * element.keypoint!
const [min, max] = pathFormula.range
const relative = pathFormula.relative
if ('editable' in pathFormula && pathFormula.editable) {
const getBaseSize = pathFormula.getBaseSize![index]
const range = pathFormula.range![index]
const relative = pathFormula.relative![index]
const keypoint = originKeypoints[index]
const baseSize = getBaseSize(element.width, element.height)
const originPos = baseSize * keypoint
const [min, max] = range
shapePathData = { baseSize, originPos, min, max, relative }
}
@ -55,19 +61,30 @@ export default (
let keypoint = 0
if (relative === 'left') keypoint = (originPos + moveX) / baseSize
if (relative === 'right') keypoint = (originPos - moveX) / baseSize
if (relative === 'center') keypoint = (originPos - moveX * 2) / baseSize
if (relative === 'top') keypoint = (originPos + moveY) / baseSize
if (relative === 'bottom') keypoint = (originPos - moveY) / baseSize
else if (relative === 'left') keypoint = (originPos + moveX) / baseSize
else if (relative === 'right') keypoint = (originPos - moveX) / baseSize
else if (relative === 'top') keypoint = (originPos + moveY) / baseSize
else if (relative === 'bottom') keypoint = (originPos - moveY) / baseSize
else if (relative === 'left_bottom') keypoint = (originPos + moveX) / baseSize
else if (relative === 'right_bottom') keypoint = (originPos - moveX) / baseSize
else if (relative === 'top_right') keypoint = (originPos + moveY) / baseSize
else if (relative === 'bottom_right') keypoint = (originPos - moveY) / baseSize
if (keypoint < min) keypoint = min
if (keypoint > max) keypoint = max
let keypoints: number[] = []
if (Array.isArray(originKeypoints)) {
keypoints = [...originKeypoints]
keypoints[index] = keypoint
}
else keypoints = [keypoint]
return {
...el,
keypoint,
path: pathFormula.formula(shapeElement.width, shapeElement.height, keypoint),
keypoints,
path: pathFormula.formula(shapeElement.width, shapeElement.height, keypoints),
}
}
return el

View File

@ -405,7 +405,7 @@ export default (
const pathFormula = SHAPE_PATH_FORMULAS[el.pathFormula]
let path = ''
if ('editable' in pathFormula) path = pathFormula.formula(width, height, el.keypoint!)
if ('editable' in pathFormula) path = pathFormula.formula(width, height, el.keypoints!)
else path = pathFormula.formula(width, height)
return {

View File

@ -224,13 +224,13 @@ const changeShape = (shape: ShapePoolItem) => {
const pathFormula = SHAPE_PATH_FORMULAS[shape.pathFormula]
if ('editable' in pathFormula) {
props.path = pathFormula.formula(width, height, pathFormula.defaultValue)
props.keypoint = pathFormula.defaultValue
props.keypoints = pathFormula.defaultValue
}
else props.path = pathFormula.formula(width, height)
}
else {
props.pathFormula = undefined
props.keypoint = undefined
props.keypoints = undefined
}
updateElement(props)
}