feat(resize-rotate): save frame data of node

This commit is contained in:
braks
2022-08-31 11:12:51 +02:00
parent 3f4e071bbf
commit c222bb9de5
3 changed files with 89 additions and 25 deletions
@@ -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
}
+33 -11
View File
@@ -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 {