refactor(resize-rotate): set fixed styles on resize rotate node
This commit is contained in:
@@ -29,12 +29,11 @@ const onPaneReady = (store: VueFlowStore) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div style="height: 100%; color: black">
|
<div style="height: 100%">
|
||||||
{{ extent }}
|
|
||||||
<VueFlow
|
<VueFlow
|
||||||
v-model="elements"
|
v-model="elements"
|
||||||
class="vue-flow-basic-example"
|
class="vue-flow-basic-example"
|
||||||
snap-to-grid
|
:snap-to-grid="true"
|
||||||
:snap-grid="[10, 10]"
|
:snap-grid="[10, 10]"
|
||||||
:prevent-scrolling="false"
|
:prevent-scrolling="false"
|
||||||
:zoom-on-scroll="false"
|
:zoom-on-scroll="false"
|
||||||
@@ -64,7 +63,7 @@ const onPaneReady = (store: VueFlowStore) => {
|
|||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
#root {
|
#root {
|
||||||
height: 1024px;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ export default [
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
},
|
},
|
||||||
dragHandle: `[data-moveable-id='1']`,
|
|
||||||
style: {
|
|
||||||
cursor: 'default',
|
|
||||||
},
|
|
||||||
data: {
|
data: {
|
||||||
style: {
|
style: {
|
||||||
background: 'rgb(255, 0, 114) none repeat scroll 0% 0%',
|
background: 'rgb(255, 0, 114) none repeat scroll 0% 0%',
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MoveableEvents, MoveableProps } from 'vue3-moveable'
|
import type { MoveableProps } from 'vue3-moveable'
|
||||||
import Moveable from 'vue3-moveable'
|
import Moveable from 'vue3-moveable'
|
||||||
import type { Position } from '@braks/vue-flow'
|
import type { Position } from '@braks/vue-flow'
|
||||||
import { Handle, useVueFlow } from '@braks/vue-flow'
|
import { Handle, useVueFlow } from '@braks/vue-flow'
|
||||||
|
import { useMoveable } from './utils'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id: string
|
id: string
|
||||||
@@ -15,43 +16,13 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const emits = defineEmits(['updateNodeInternals'])
|
const emits = defineEmits(['updateNodeInternals'])
|
||||||
|
|
||||||
const {
|
const { findNode, onPaneClick, onNodeClick, onNodeDragStart, snapGrid, snapToGrid } = useVueFlow()
|
||||||
viewport,
|
|
||||||
updateNodeDimensions,
|
|
||||||
onPaneClick,
|
|
||||||
onPaneScroll,
|
|
||||||
onPaneContextMenu,
|
|
||||||
getNode,
|
|
||||||
onNodeClick,
|
|
||||||
onNodeDragStart,
|
|
||||||
snapGrid,
|
|
||||||
snapToGrid,
|
|
||||||
} = useVueFlow()
|
|
||||||
|
|
||||||
const el = ref()
|
const el = ref()
|
||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
|
|
||||||
const frame = {
|
const { onRotateStart, onRotate, onResizeStart, onResize } = useMoveable(props.id, emits)
|
||||||
rotate: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
const onResize = (e: MoveableEvents['resize']) => {
|
|
||||||
e.target.style.width = `${e.width}px`
|
|
||||||
e.target.style.height = `${e.height}px`
|
|
||||||
e.target.style.left = `${e.drag.left}px`
|
|
||||||
e.target.style.top = `${e.drag.top}px`
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRotateStart = (e: MoveableEvents['rotateStart']) => {
|
|
||||||
e.set(frame.rotate)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRotate = (e: MoveableEvents['rotate']) => {
|
|
||||||
frame.rotate = e.beforeRotate
|
|
||||||
e.target.style.transform = `rotate(${e.beforeRotate}deg)`
|
|
||||||
emits('updateNodeInternals')
|
|
||||||
}
|
|
||||||
|
|
||||||
const toggleVisibility = (val?: boolean) => {
|
const toggleVisibility = (val?: boolean) => {
|
||||||
visible.value = val ?? !visible.value
|
visible.value = val ?? !visible.value
|
||||||
@@ -66,6 +37,21 @@ onNodeDragStart(({ node }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onPaneClick(() => toggleVisibility(false))
|
onPaneClick(() => toggleVisibility(false))
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
const node = findNode(props.id)!
|
||||||
|
|
||||||
|
node.dragHandle = `[data-moveable-id='${props.id}']`
|
||||||
|
|
||||||
|
const previousStyle = node.style
|
||||||
|
node.style = () => {
|
||||||
|
return {
|
||||||
|
...previousStyle,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
cursor: 'default',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -75,15 +61,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div ref="el" style="cursor: grab; pointer-events: all" :data-moveable-id="props.id" :style="data.style">
|
||||||
ref="el"
|
|
||||||
:data-moveable-id="props.id"
|
|
||||||
:style="{
|
|
||||||
cursor: 'grab',
|
|
||||||
...data.style,
|
|
||||||
}"
|
|
||||||
style="position: relative"
|
|
||||||
>
|
|
||||||
<Handle type="target" :position="props.targetPosition" />
|
<Handle type="target" :position="props.targetPosition" />
|
||||||
|
|
||||||
<slot>
|
<slot>
|
||||||
@@ -94,13 +72,12 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Moveable
|
<Moveable
|
||||||
v-if="visible"
|
|
||||||
v-bind="props.moveableProps"
|
v-bind="props.moveableProps"
|
||||||
class-name="nodrag"
|
class-name="nodrag"
|
||||||
:target="[`[data-moveable-id='${props.id}']`]"
|
style="pointer-events: all"
|
||||||
|
:target="visible ? el : undefined"
|
||||||
:resizable="true"
|
:resizable="true"
|
||||||
:rotatable="true"
|
:rotatable="true"
|
||||||
:draggable="true"
|
|
||||||
:snappable="snapToGrid"
|
:snappable="snapToGrid"
|
||||||
:snap-element="snapToGrid"
|
:snap-element="snapToGrid"
|
||||||
:snap-gap="snapToGrid"
|
:snap-gap="snapToGrid"
|
||||||
@@ -108,17 +85,17 @@ export default {
|
|||||||
:snap-digit="snapGrid[0]"
|
:snap-digit="snapGrid[0]"
|
||||||
:snap-treshold="snapGrid[0]"
|
:snap-treshold="snapGrid[0]"
|
||||||
:snap-grid-width="snapGrid[0]"
|
:snap-grid-width="snapGrid[0]"
|
||||||
:snap-grid-height="snapGrid[0]"
|
:snap-grid-height="snapGrid[1]"
|
||||||
rotation-position="top"
|
|
||||||
:padding="{ left: 0, top: 0, right: 0, bottom: 0 }"
|
:padding="{ left: 0, top: 0, right: 0, bottom: 0 }"
|
||||||
:origin="false"
|
:origin="false"
|
||||||
:edge="true"
|
|
||||||
:start-drag-rotate="0"
|
:start-drag-rotate="0"
|
||||||
:throttle-drag-rotate="0"
|
:throttle-drag-rotate="0"
|
||||||
:throttle-resize="1"
|
:throttle-resize="1"
|
||||||
:render-directions="['nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se']"
|
:render-directions="['nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se']"
|
||||||
:zoom="1"
|
:zoom="1"
|
||||||
|
@resize-start="onResizeStart"
|
||||||
@resize="onResize"
|
@resize="onResize"
|
||||||
|
@rotate-start="onRotateStart"
|
||||||
@rotate="onRotate"
|
@rotate="onRotate"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import type { Able, MoveableEvents, MoveableManagerInterface } from 'vue3-moveable'
|
||||||
|
|
||||||
|
export function useMoveable(id: string, emits: (event: 'updateNodeInternals') => void) {
|
||||||
|
const frame = reactive({
|
||||||
|
translate: [0, 0],
|
||||||
|
rotate: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const onResizeStart = (e: MoveableEvents['resizeStart']) => {
|
||||||
|
e.setOrigin(['%', '%'])
|
||||||
|
|
||||||
|
if (e.dragStart) {
|
||||||
|
e.dragStart.set(frame.translate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onResize = (e: MoveableEvents['resize']) => {
|
||||||
|
frame.translate = e.drag.beforeTranslate
|
||||||
|
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)`
|
||||||
|
}
|
||||||
|
|
||||||
|
const onRotateStart = (e: MoveableEvents['rotateStart']) => {
|
||||||
|
e.set(frame.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)`
|
||||||
|
|
||||||
|
emits('updateNodeInternals')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
onResizeStart,
|
||||||
|
onResize,
|
||||||
|
onRotateStart,
|
||||||
|
onRotate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DimensionViewable = {
|
||||||
|
name: 'dimensionViewable',
|
||||||
|
props: {},
|
||||||
|
events: {},
|
||||||
|
render(moveable: MoveableManagerInterface<any, any>, renderer) {
|
||||||
|
const rect = moveable.getRect()
|
||||||
|
|
||||||
|
// Add key (required)
|
||||||
|
// Add class prefix moveable-(required)
|
||||||
|
return renderer.createElement(
|
||||||
|
'div',
|
||||||
|
{
|
||||||
|
key: 'dimension-viewer',
|
||||||
|
class: 'moveable-dimension',
|
||||||
|
style: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: `${rect.width / 2}px`,
|
||||||
|
top: `${rect.height + 20}px`,
|
||||||
|
background: '#4af',
|
||||||
|
borderRadius: '2px',
|
||||||
|
padding: '2px 4px',
|
||||||
|
color: 'white',
|
||||||
|
fontSize: '13px',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
willChange: 'transform',
|
||||||
|
transform: 'translate(-50%, 0px)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
`${Math.round(rect.offsetWidth)} x ${Math.round(rect.offsetHeight)}`,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
} as Able<{}, {}>
|
||||||
@@ -154,16 +154,20 @@ export default {
|
|||||||
<slot :name="`node-${nodeName}`" />
|
<slot :name="`node-${nodeName}`" />
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #edges>
|
<template #edges>
|
||||||
<template v-for="edgeName of Object.keys(getEdgeTypes)">
|
<template v-for="edgeName of Object.keys(getEdgeTypes)">
|
||||||
<slot :name="`edge-${edgeName}`" />
|
<slot :name="`edge-${edgeName}`" />
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #connection-name>
|
<template #connection-name>
|
||||||
<slot name="connection-line" />
|
<slot name="connection-line" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot name="zoom-pane" />
|
<slot name="zoom-pane" />
|
||||||
</Viewport>
|
</Viewport>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user