Files
svgeditor2.0/src/components/mt-edit/components/draw-line-render/index.vue
2025-09-25 11:34:55 +08:00

197 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<svg
:id="lineRenderProps.itemJson.id"
class="mt-line-render"
:style="{
position: 'absolute',
left: `${-offset}px`,
top: `${-offset}px`,
width: `${lineRenderProps.canvasCfg.width + offset}px`,
height: `${lineRenderProps.canvasCfg.height + offset}px`
}"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
pointer-events="none"
>
<g>
<defs>
<marker
:id="'markerArrowStart' + lineRenderProps.itemJson.id"
viewBox="0 0 10 10"
refX="8"
refY="5"
markerWidth="6"
markerHeight="6"
orient="auto-start-reverse"
>
<path d="M 0 0 L 10 5 L 0 10 z" :fill="lineRenderProps.itemJson.props.stroke.val" />
</marker>
<marker
:id="'markerArrowEnd' + lineRenderProps.itemJson.id"
viewBox="0 0 10 10"
refX="8"
refY="5"
markerWidth="6"
markerHeight="6"
orient="auto"
>
<path d="M 0 0 L 10 5 L 0 10 z" :fill="lineRenderProps.itemJson.props.stroke.val" />
</marker>
</defs>
<path
:d="
positionArrarToPath(
lineRenderProps.itemJson.props.point_position.val,
lineRenderProps.itemJson.binfo.left + offset,
lineRenderProps.itemJson.binfo.top + offset
)
"
pointer-events="visibleStroke"
fill="none"
:stroke="
lineRenderProps.itemJson.props.ani_type.val === 'electricity'
? lineRenderProps.itemJson.props.ani_color.val
: lineRenderProps.itemJson.props.stroke.val
"
:stroke-width="lineRenderProps.itemJson.props['stroke-width'].val"
style="cursor: move"
stroke-dashoffset="0"
:stroke-dasharray="
lineRenderProps.itemJson.props.ani_type.val === 'electricity'
? lineRenderProps.itemJson.props['stroke-width'].val * 3
: 0
"
:marker-start="
lineRenderProps.itemJson.props?.['marker-start']?.val
? `url(#markerArrowStart${lineRenderProps.itemJson.id})`
: ''
"
:marker-end="
lineRenderProps.itemJson.props?.['marker-end']?.val
? `url(#markerArrowEnd${lineRenderProps.itemJson.id})`
: ''
"
class="real"
>
<animate
v-if="lineRenderProps.itemJson.props.ani_type.val === 'electricity'"
attributeName="stroke-dashoffset"
:from="lineRenderProps.itemJson.props.ani_reverse.val ? 0 : 1000"
:to="
lineRenderProps.itemJson.props.ani_reverse.val
? lineRenderProps.itemJson.props.ani_play.val
? 1000
: 0
: lineRenderProps.itemJson.props.ani_play.val
? 0
: 1000
"
:dur="`${
lineRenderProps.itemJson.props.ani_dur.val < 1 ? 1 : lineRenderProps.itemJson.props.ani_dur.val
}s`"
repeatCount="indefinite"
/>
</path>
</g>
</svg>
</template>
<script setup lang="ts">
import type { MouseTouchEvent } from '@/components/mt-dzr/utils/types'
import type { IDoneJson, IGlobalStoreCanvasCfg, IGlobalStoreGridCfg } from '../../store/types'
import { alignToGrid, positionArrarToPath } from '@/components/mt-edit/utils'
import { computed } from 'vue'
import { configStore } from '../../store/config'
type LineRenderProps = {
itemJson: IDoneJson
canvasCfg: IGlobalStoreCanvasCfg
grid: IGlobalStoreGridCfg
canvasDom: HTMLElement | null
mode: 'pen' | 'pencil'
}
const lineRenderProps = withDefaults(defineProps<LineRenderProps>(), {
mode: 'pen'
})
const lineRenderEmits = defineEmits(['drawLineEnd'])
const offset = configStore.lineRenderOffset
//如果网格关闭或者没有开启网格对齐网格大小为1
const grid_align_size = computed(() =>
!lineRenderProps.grid.align || !lineRenderProps.grid.enabled ? 1 : lineRenderProps.grid.size
)
const onMouseDown = (de: MouseTouchEvent, point_index: number, item: { x: number; y: number }) => {
de.stopPropagation()
// 记录鼠标按下时实际点的坐标
const { x: realityX, y: realityY } = item
// 记录最开始点击时鼠标位置
const d_x = de instanceof MouseEvent ? de.clientX : de.touches[0].pageX
const d_y = de instanceof MouseEvent ? de.clientY : de.touches[0].pageY
let new_x = 0
let new_y = 0
const onMouseMove = (e: MouseTouchEvent) => {
// 记录鼠标移动的位置
const m_x = e instanceof MouseEvent ? e.clientX : e.touches[0].pageX
const m_y = e instanceof MouseEvent ? e.clientY : e.touches[0].pageY
// 移动的距离
const move_x = de.ctrlKey ? 0 : alignToGrid((m_x - d_x) / lineRenderProps.canvasCfg.scale, 1) //感觉对齐网格有点体验不好 所以固定为一了
const move_y = de.shiftKey ? 0 : alignToGrid((m_y - d_y) / lineRenderProps.canvasCfg.scale, 1)
new_x = realityX + move_x
new_y = realityY + move_y
if (lineRenderProps.mode == 'pencil') {
const new_point_position = lineRenderProps.itemJson.props.point_position.val
new_point_position.push({
x: new_x,
y: new_y
})
return
} else {
const new_point_position = lineRenderProps.itemJson.props.point_position.val
new_point_position[point_index].x = new_x
new_point_position[point_index].y = new_y
}
}
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove)
document.removeEventListener('mouseup', onMouseUp)
document.removeEventListener('touchmove', onMouseMove)
document.removeEventListener('touchend', onMouseUp)
const itemRect = document.querySelector(`#${lineRenderProps.itemJson.id} g .real`)!.getBoundingClientRect()
const canvas_area_bounding_info = lineRenderProps.canvasDom!.getBoundingClientRect()
const new_left = (itemRect?.left - canvas_area_bounding_info?.left) / lineRenderProps.canvasCfg.scale
const new_top = (itemRect?.top - canvas_area_bounding_info?.top) / lineRenderProps.canvasCfg.scale
const move_x = new_left - lineRenderProps.itemJson.binfo.left
const move_y = new_top - lineRenderProps.itemJson.binfo.top
const new_item_json = {
...lineRenderProps.itemJson,
binfo: {
...lineRenderProps.itemJson.binfo,
left: new_left,
top: new_top,
width: itemRect?.width / lineRenderProps.canvasCfg.scale,
height: itemRect?.height / lineRenderProps.canvasCfg.scale
},
props: {
...lineRenderProps.itemJson.props,
point_position: {
...lineRenderProps.itemJson.props.point_position,
val: lineRenderProps.itemJson.props.point_position.val.map((m: { x: number; y: number }) => {
return {
x: m.x - move_x,
y: m.y - move_y
}
})
}
}
}
lineRenderEmits('drawLineEnd', new_item_json)
}
document.addEventListener('mousemove', onMouseMove)
document.addEventListener('mouseup', onMouseUp)
document.addEventListener('touchmove', onMouseMove)
document.addEventListener('touchend', onMouseUp)
}
defineExpose({
onMouseDown
})
</script>
<style scoped></style>