feat(resize-rotate): save frame data of node
This commit is contained in:
@@ -1,20 +1,23 @@
|
||||
<script lang="ts" setup>
|
||||
import type { MoveableProps } from 'vue3-moveable'
|
||||
import Moveable from 'vue3-moveable'
|
||||
import type { Position } from '@braks/vue-flow'
|
||||
import type { Dimensions } from '@braks/vue-flow'
|
||||
import { Handle, useVueFlow } from '@braks/vue-flow'
|
||||
import { useMoveable } from './utils'
|
||||
import type { ResizeRotateNodeProps } from './types'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
label: string
|
||||
targetPosition: Position
|
||||
sourcePosition: Position
|
||||
data: any
|
||||
moveableProps?: MoveableProps
|
||||
}>()
|
||||
interface Emits {
|
||||
(event: 'updateNodeInternals'): void
|
||||
(event: 'resize', dimensions: Dimensions): void
|
||||
(event: 'rotate', rotation: number): void
|
||||
}
|
||||
|
||||
const emits = defineEmits(['updateNodeInternals'])
|
||||
const props = withDefaults(defineProps<ResizeRotateNodeProps>(), {
|
||||
resizable: true,
|
||||
rotatable: true,
|
||||
moveableProps: () => ({}),
|
||||
})
|
||||
|
||||
const emits = defineEmits<Emits>()
|
||||
|
||||
const { findNode, onPaneClick, onNodeClick, onNodeDragStart, snapGrid, snapToGrid } = useVueFlow()
|
||||
|
||||
@@ -61,7 +64,19 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="el" style="cursor: grab; pointer-events: all" :data-moveable-id="props.id" :style="data.style">
|
||||
<div
|
||||
ref="el"
|
||||
style="cursor: grab; pointer-events: all"
|
||||
:data-moveable-id="props.id"
|
||||
:style="{
|
||||
...data.style,
|
||||
cursor: visible ? 'grab' : 'auto',
|
||||
zIndex: visible ? 1000 : 0,
|
||||
width: data.dimensions?.width ? `${data.dimensions.width}px` : undefined,
|
||||
height: data.dimensions?.height ? `${data.dimensions.height}px` : undefined,
|
||||
transform: `translate(${data.translate[0]}px, ${data.translate[1]}px)` + ` rotate(${data.rotate}deg)`,
|
||||
}"
|
||||
>
|
||||
<Handle type="target" :position="props.targetPosition" />
|
||||
|
||||
<slot>
|
||||
@@ -76,8 +91,8 @@ export default {
|
||||
class-name="nodrag"
|
||||
style="pointer-events: all"
|
||||
:target="visible ? el : undefined"
|
||||
:resizable="true"
|
||||
:rotatable="true"
|
||||
:resizable="resizable"
|
||||
:rotatable="rotatable"
|
||||
:snappable="snapToGrid"
|
||||
:snap-element="snapToGrid"
|
||||
:snap-gap="snapToGrid"
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { Dimensions, ElementData, Position } from '@braks/vue-flow'
|
||||
import type { MoveableProps } from 'vue3-moveable'
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
export interface ResizeRotateNodeEmits {
|
||||
(event: 'updateNodeInternals'): void
|
||||
(event: 'resize', dimensions: Dimensions): void
|
||||
(event: 'rotate', rotation: number): void
|
||||
}
|
||||
|
||||
export interface ResizeRotateNodeData extends ElementData {
|
||||
rotate: number
|
||||
translate: number[]
|
||||
dimensions: Dimensions
|
||||
style: CSSProperties
|
||||
}
|
||||
|
||||
export interface ResizeRotateNodeProps {
|
||||
id: string
|
||||
label: string
|
||||
targetPosition: Position
|
||||
sourcePosition: Position
|
||||
resizable?: boolean
|
||||
rotatable?: boolean
|
||||
data: ResizeRotateNodeData
|
||||
moveableProps?: MoveableProps
|
||||
}
|
||||
@@ -1,35 +1,57 @@
|
||||
import type { Able, MoveableEvents, MoveableManagerInterface } from 'vue3-moveable'
|
||||
import type { GraphNode } from '@braks/vue-flow'
|
||||
import { useVueFlow } from '@braks/vue-flow'
|
||||
import type { ResizeRotateNodeData, ResizeRotateNodeEmits } from './types'
|
||||
|
||||
export function useMoveable(id: string, emits: (event: 'updateNodeInternals') => void) {
|
||||
const frame = reactive({
|
||||
translate: [0, 0],
|
||||
rotate: 0,
|
||||
})
|
||||
export function useMoveable(id: string, emits: ResizeRotateNodeEmits) {
|
||||
const { findNode } = useVueFlow()
|
||||
const node = findNode(id)! as GraphNode<ResizeRotateNodeData>
|
||||
|
||||
if (!node.data) {
|
||||
node.data = {
|
||||
translate: [0, 0],
|
||||
rotate: 0,
|
||||
style: {},
|
||||
dimensions: { width: NaN, height: NaN },
|
||||
}
|
||||
}
|
||||
if (!node.data.style) node.data.style = {}
|
||||
if (!node.data.rotate) node.data.rotate = 0
|
||||
if (!node.data.translate) node.data.translate = [0, 0]
|
||||
if (!node.data.dimensions) node.data.dimensions = { width: NaN, height: NaN }
|
||||
|
||||
const onResizeStart = (e: MoveableEvents['resizeStart']) => {
|
||||
e.setOrigin(['%', '%'])
|
||||
|
||||
if (e.dragStart) {
|
||||
e.dragStart.set(frame.translate)
|
||||
e.dragStart.set(node.data!.translate)
|
||||
}
|
||||
}
|
||||
|
||||
const onResize = (e: MoveableEvents['resize']) => {
|
||||
frame.translate = e.drag.beforeTranslate
|
||||
node.data!.translate = e.drag.beforeTranslate
|
||||
node.data!.dimensions = { width: e.width, height: e.height }
|
||||
|
||||
e.target.style.width = `${e.width}px`
|
||||
e.target.style.height = `${e.height}px`
|
||||
e.target.style.transform = `translate(${frame.translate[0]}px, ${frame.translate[1]}px)` + ` rotate(${frame.rotate}deg)`
|
||||
e.target.style.transform =
|
||||
`translate(${node.data!.translate[0]}px, ${node.data!.translate[1]}px)` + ` rotate(${node.data!.rotate}deg)`
|
||||
|
||||
emits('resize', { width: e.width, height: e.height })
|
||||
}
|
||||
|
||||
const onRotateStart = (e: MoveableEvents['rotateStart']) => {
|
||||
e.set(frame.rotate)
|
||||
e.set(node.data!.rotate)
|
||||
}
|
||||
|
||||
const onRotate = (e: MoveableEvents['rotate']) => {
|
||||
frame.rotate = e.beforeRotate
|
||||
e.target.style.transform = `translate(${frame.translate[0]}px, ${frame.translate[1]}px)` + ` rotate(${frame.rotate}deg)`
|
||||
node.data!.rotate = e.beforeRotate
|
||||
|
||||
e.target.style.transform =
|
||||
`translate(${node.data!.translate[0]}px, ${node.data!.translate[1]}px)` + ` rotate(${node.data!.rotate}deg)`
|
||||
|
||||
emits('updateNodeInternals')
|
||||
emits('rotate', node.data!.rotate)
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user