fix: edge anchor

This commit is contained in:
Braks
2021-10-20 19:11:23 +02:00
parent 8c54daedc0
commit 7ecbcba7eb
9 changed files with 54 additions and 68 deletions

View File

@@ -25,11 +25,13 @@ const sourceHandleStyleB: CSSProperties = { ...targetHandleStyle, bottom: '10px'
const onConnect = (params: Connection | Edge) => console.log('handle onConnect', params)
</script>
<template>
<Handle type="target" :position="Position.Left" :style="targetHandleStyle" :on-connect="onConnect" />
<div>
Custom Color Picker Node: <strong>{{ data.color }}</strong>
<div class="revue-flow__node-color-selector">
<Handle type="target" :position="Position.Left" :style="targetHandleStyle" :on-connect="onConnect" />
<div>
Custom Color Picker Node: <strong>{{ data.color }}</strong>
</div>
<input class="nodrag" type="color" :value="data.color" @input="props.data.onChange" />
<Handle id="a" type="source" :position="Position.Right" :style="sourceHandleStyleA" />
<Handle id="b" type="source" :position="Position.Right" :style="sourceHandleStyleB" />
</div>
<input class="nodrag" type="color" :value="data.color" @input="props.data.onChange" />
<Handle id="a" type="source" :position="Position.Right" :style="sourceHandleStyleA" />
<Handle id="b" type="source" :position="Position.Right" :style="sourceHandleStyleB" />
</template>

View File

@@ -47,9 +47,7 @@ onMounted(() => {
if (isEdge(e) || e.id !== '2') {
return e
}
const color = (event.target as HTMLInputElement).value
bgColor.value = color
return {

View File

@@ -87,7 +87,9 @@ const onEdgeUpdaterTargetMouseDown = (event: MouseEvent) => {
const updating = ref<boolean>(false)
const onEdgeUpdaterMouseEnter = () => (updating.value = true)
const onEdgeUpdaterMouseOut = () => (updating.value = false)
const isVisible = ({ sourceX, sourceY, targetX, targetY }: ReturnType<typeof getEdgePositions>) => {
return store.onlyRenderVisibleElements
? isEdgeVisible({
@@ -99,14 +101,14 @@ const isVisible = ({ sourceX, sourceY, targetX, targetY }: ReturnType<typeof get
})
: true
}
const edgePos = computed(() =>
getEdgePositions(props.nodes.sourceNode, sourceHandle, sourcePosition, props.nodes.targetNode, targetHandle, targetPosition),
)
const visible = computed(() => !props.edge.isHidden && isVisible(edgePos.value))
</script>
<template>
<g
v-if="visible"
v-if="!props.edge.isHidden && isVisible(edgePos)"
:class="[
'revue-flow__edge',
`revue-flow__edge-${props.type.name || 'default'}`,
@@ -189,9 +191,9 @@ const visible = computed(() => !props.edge.isHidden && isVisible(edgePos.value))
</g>
<g @mousedown="onEdgeUpdaterTargetMouseDown" @mouseenter="onEdgeUpdaterMouseEnter" @mouseout="onEdgeUpdaterMouseOut">
<EdgeAnchor
:position="sourcePosition"
:center-x="edgePos.sourceX"
:center-y="edgePos.sourceY"
:position="targetPosition"
:center-x="edgePos.targetX"
:center-y="edgePos.targetY"
:radius="props.edgeUpdaterRadius"
/>
</g>

View File

@@ -29,16 +29,12 @@ const selectedNodes = computed(() =>
: [],
)
const style = computed(() => ({
transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`,
}))
const innerStyle = computed(() => ({
const innerStyle = {
width: `${store.selectedNodesBbox.width}px`,
height: `${store.selectedNodesBbox.height}px`,
top: `${store.selectedNodesBbox.y}px`,
left: `${store.selectedNodesBbox.x}px`,
}))
}
const onStart: DraggableEventListener = ({ event }) => {
hooks.selectionDragStart.trigger({ event, nodes: selectedNodes.value })
@@ -73,7 +69,12 @@ const onContextMenu = (event: MouseEvent) => {
}
</script>
<template>
<div class="revue-flow__nodesselection" :style="style">
<div
class="revue-flow__nodesselection"
:style="{
transform: `translate(${store.transform[0]}px,${store.transform[1]}px) scale(${store.transform[2]})`,
}"
>
<Draggable
:scale="store.transform[2]"
:grid="store.snapToGrid ? store.snapGrid : undefined"

View File

@@ -8,21 +8,15 @@ const el = templateRef('user-selection', null)
const onMouseDown = (event: MouseEvent) => {
const mousePos = getMousePosition(event)
if (!mousePos) {
return
}
if (!mousePos) return
store.setUserSelection(mousePos)
}
const onMouseMove = (event: MouseEvent) => {
if (!store.selectionActive) {
return
}
if (!store.selectionActive) return
const mousePos = getMousePosition(event)
if (!mousePos) {
return
}
if (!mousePos) return
store.updateUserSelection(mousePos)
}
@@ -41,17 +35,15 @@ useEventListener(el, 'mousemove', onMouseMove)
useEventListener(el, 'click', onMouseUp)
useEventListener(el, 'mouseup', onMouseUp)
useEventListener(el, 'mouseleave', onMouseLeave)
const userSelectionRect = computed(() => store.userSelectionRect)
</script>
<template>
<div ref="user-selection" class="revue-flow__selectionpane">
<SelectionRect
v-if="userSelectionRect.draw"
:width="userSelectionRect.width"
:height="userSelectionRect.height"
:x="userSelectionRect.x"
:y="userSelectionRect.y"
v-if="store.userSelectionRect.draw"
:width="store.userSelectionRect.width"
:height="store.userSelectionRect.height"
:x="store.userSelectionRect.x"
:y="store.userSelectionRect.y"
/>
</div>
</template>

View File

@@ -3,9 +3,10 @@ import { pointer, select } from 'd3-selection'
import { Ref } from 'vue'
import { get } from '@vueuse/core'
import { FlowTransform, PanOnScrollMode, Transform, UseZoom, UseZoomOptions } from '~/types'
import { clamp } from '~/utils'
import { clamp, onLoadGetElements, onLoadProject, onLoadToObject } from '~/utils'
import useKeyPress from '~/composables/useKeyPress'
import { Hooks, Store } from '~/context'
import { useZoomPanHelper } from '~/composables/index'
const viewChanged = (prevTransform: FlowTransform, eventTransform: ZoomTransform): boolean =>
prevTransform.x !== eventTransform.x || prevTransform.y !== eventTransform.y || prevTransform.zoom !== eventTransform.k
@@ -59,6 +60,18 @@ export default function (el: Ref<HTMLDivElement>, options: UseZoomOptions): UseZ
const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom)
d3z.transform(d3s, updatedTransform)
store.initD3Zoom({ d3Zoom: d3z, d3Selection: d3s, d3ZoomHandler })
const { zoomIn, zoomOut, zoomTo, transform: setTransform, fitView } = useZoomPanHelper(store)
hooks.load.trigger({
fitView: (params = { padding: 0.1 }) => fitView(params),
zoomIn,
zoomOut,
zoomTo,
setTransform,
project: onLoadProject(store),
getElements: onLoadGetElements(store),
toObject: onLoadToObject(store),
})
const applyZoomHandlers = () => {
d3z.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => {
if (viewChanged(prevTransform.value, event.transform)) {

View File

@@ -5,8 +5,7 @@ import { Store } from '~/context'
const DEFAULT_PADDING = 0.1
export default function (): UseZoomPanHelper {
const store = inject(Store)!
export default function (store = inject(Store)!): UseZoomPanHelper {
return {
zoomIn: () => store.d3Selection && store.d3Zoom?.scaleBy(store.d3Selection, 1.2),
zoomOut: () => store.d3Selection && store.d3Zoom?.scaleBy(store.d3Selection, 1 / 1.2),

View File

@@ -37,21 +37,15 @@ const hooks = inject(Hooks)!
const zoomPaneEl = templateRef<HTMLDivElement>('zoom-pane', null)
const { transform } = useZoom(zoomPaneEl, props)
const { width, height } = useElementBounding(zoomPaneEl)
watch(width, (val) => (store.dimensions.width = val), { flush: 'post' })
watch(height, (val) => (store.dimensions.height = val), { flush: 'post' })
watch(transform, (val) => (store.transform = val), { flush: 'post' })
watch(width, (val) => (store.dimensions.width = val))
watch(height, (val) => (store.dimensions.height = val))
watch(transform, (val) => (store.transform = val))
const { zoomIn, zoomOut, zoomTo, transform: setTransform, fitView } = useZoomPanHelper()
hooks.load.trigger({
fitView: (params = { padding: 0.1 }) => fitView(params),
zoomIn,
zoomOut,
zoomTo,
setTransform,
project: onLoadProject(store),
getElements: onLoadGetElements(store),
toObject: onLoadToObject(store),
})
store.transform = transform.value
store.dimensions = {
width: width.value,
height: height.value,
}
</script>
<template>
<div ref="zoom-pane" class="revue-flow__renderer revue-flow__zoompane">

15
src/shims-tsx.d.ts vendored
View File

@@ -1,15 +0,0 @@
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// @ts-ignore
interface ElementClass extends Vue {}
interface IntrinsicAttributes {
[prop: string]: any
}
}
}