| <template> | |
| <div class="line-element-operate"> | |
| <template v-if="handlerVisible"> | |
| <ResizeHandler | |
| class="operate-resize-handler" | |
| v-for="point in resizeHandlers" | |
| :key="point.handler" | |
| :style="point.style" | |
| @mousedown.stop="$event => dragLineElement($event, elementInfo, point.handler)" | |
| /> | |
| <svg | |
| :width="svgWidth || 1" | |
| :height="svgHeight || 1" | |
| :stroke="elementInfo.color" | |
| overflow="visible" | |
| :style="{ transform: `scale(${canvasScale})` }" | |
| > | |
| <template v-if="elementInfo.curve"> | |
| <g> | |
| <line class="anchor-line" :x1="elementInfo.start[0]" :y1="elementInfo.start[1]" :x2="elementInfo.curve[0]" :y2="elementInfo.curve[1]"></line> | |
| <line class="anchor-line" :x1="elementInfo.end[0]" :y1="elementInfo.end[1]" :x2="elementInfo.curve[0]" :y2="elementInfo.curve[1]"></line> | |
| </g> | |
| </template> | |
| <template v-if="elementInfo.cubic"> | |
| <g v-for="(item, index) in elementInfo.cubic" :key="index"> | |
| <line class="anchor-line" v-if="index === 0" :x1="elementInfo.start[0]" :y1="elementInfo.start[1]" :x2="item[0]" :y2="item[1]"></line> | |
| <line class="anchor-line" v-if="index === 1" :x1="elementInfo.end[0]" :y1="elementInfo.end[1]" :x2="item[0]" :y2="item[1]"></line> | |
| </g> | |
| </template> | |
| </svg> | |
| </template> | |
| </div> | |
| </template> | |
| <script lang="ts"> | |
| export default { | |
| inheritAttrs: false, | |
| } | |
| </script> | |
| <script lang="ts" setup> | |
| import { computed } from 'vue' | |
| import { storeToRefs } from 'pinia' | |
| import { useMainStore } from '@/store' | |
| import type { PPTLineElement } from '@/types/slides' | |
| import { OperateLineHandlers } from '@/types/edit' | |
| import ResizeHandler from './ResizeHandler.vue' | |
| const props = defineProps<{ | |
| elementInfo: PPTLineElement | |
| handlerVisible: boolean | |
| dragLineElement: (e: MouseEvent, element: PPTLineElement, command: OperateLineHandlers) => void | |
| }>() | |
| const { canvasScale } = storeToRefs(useMainStore()) | |
| const svgWidth = computed(() => Math.max(props.elementInfo.start[0], props.elementInfo.end[0])) | |
| const svgHeight = computed(() => Math.max(props.elementInfo.start[1], props.elementInfo.end[1])) | |
| const resizeHandlers = computed(() => { | |
| const handlers = [ | |
| { | |
| handler: OperateLineHandlers.START, | |
| style: { | |
| left: props.elementInfo.start[0] * canvasScale.value + 'px', | |
| top: props.elementInfo.start[1] * canvasScale.value + 'px', | |
| } | |
| }, | |
| { | |
| handler: OperateLineHandlers.END, | |
| style: { | |
| left: props.elementInfo.end[0] * canvasScale.value + 'px', | |
| top: props.elementInfo.end[1] * canvasScale.value + 'px', | |
| } | |
| }, | |
| ] | |
| if (props.elementInfo.curve || props.elementInfo.broken || props.elementInfo.broken2) { | |
| const ctrlHandler = (props.elementInfo.curve || props.elementInfo.broken || props.elementInfo.broken2) as [number, number] | |
| handlers.push({ | |
| handler: OperateLineHandlers.C, | |
| style: { | |
| left: ctrlHandler[0] * canvasScale.value + 'px', | |
| top: ctrlHandler[1] * canvasScale.value + 'px', | |
| } | |
| }) | |
| } | |
| else if (props.elementInfo.cubic) { | |
| const [ctrlHandler1, ctrlHandler2] = props.elementInfo.cubic | |
| handlers.push({ | |
| handler: OperateLineHandlers.C1, | |
| style: { | |
| left: ctrlHandler1[0] * canvasScale.value + 'px', | |
| top: ctrlHandler1[1] * canvasScale.value + 'px', | |
| } | |
| }) | |
| handlers.push({ | |
| handler: OperateLineHandlers.C2, | |
| style: { | |
| left: ctrlHandler2[0] * canvasScale.value + 'px', | |
| top: ctrlHandler2[1] * canvasScale.value + 'px', | |
| } | |
| }) | |
| } | |
| return handlers | |
| }) | |
| </script> | |
| <style lang="scss" scoped> | |
| svg { | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| pointer-events: none; | |
| transform-origin: 0 0; | |
| } | |
| .anchor-line { | |
| stroke-width: 1px; | |
| stroke-dasharray: 5 5; | |
| opacity: .5; | |
| } | |
| </style> |