feat: Show connection lines when holding down on handle

This commit is contained in:
Braks
2021-07-09 16:09:58 +02:00
parent 8f34d9d486
commit ea98c2afa1
7 changed files with 72 additions and 69 deletions
+65 -53
View File
@@ -1,4 +1,4 @@
import { ref, defineComponent, CSSProperties, PropType } from 'vue'; import { ref, defineComponent, CSSProperties, PropType, computed } from 'vue';
import { getBezierPath } from '../Edges/BezierEdge'; import { getBezierPath } from '../Edges/BezierEdge';
import { getSmoothStepPath } from '../Edges/SmoothStepEdge'; import { getSmoothStepPath } from '../Edges/SmoothStepEdge';
@@ -79,44 +79,52 @@ const ConnectionLine = defineComponent({
CustomConnectionLineComponent: { CustomConnectionLineComponent: {
type: Object as PropType<ConnectionLineProps['CustomConnectionLineComponent']>, type: Object as PropType<ConnectionLineProps['CustomConnectionLineComponent']>,
required: false, required: false,
default: () => ({}) default: undefined
} }
}, },
setup(props) { setup(props) {
console.log('connectionline');
const sourceNode = ref<Node | null>(props.nodes.find((n) => n.id === props.connectionNodeId) || null); const sourceNode = ref<Node | null>(props.nodes.find((n) => n.id === props.connectionNodeId) || null);
if (!sourceNode.value || !props.isConnectable) { if (!sourceNode.value || !props.isConnectable) {
return null; return null;
} }
const sourceHandle = props.connectionHandleId const sourceHandle = computed(() =>
? sourceNode.value.__rf.handleBounds[props.connectionHandleType].find( props.connectionHandleId
(d: HandleElement) => d.id === props.connectionHandleId ? sourceNode.value?.__rf.handleBounds[props.connectionHandleType].find(
) (d: HandleElement) => d.id === props.connectionHandleId
: sourceNode.value.__rf.handleBounds[props.connectionHandleType][0]; )
const sourceHandleX = sourceHandle ? sourceHandle.x + sourceHandle.width / 2 : sourceNode.value.__rf.width / 2; : sourceNode.value?.__rf.handleBounds[props.connectionHandleType][0]
const sourceHandleY = sourceHandle ? sourceHandle.y + sourceHandle.height / 2 : sourceNode.value.__rf.height; );
const sourceX = sourceNode.value.__rf.position.x + sourceHandleX; const sourceHandleX = computed(() =>
const sourceY = sourceNode.value.__rf.position.y + sourceHandleY; sourceHandle.value ? sourceHandle.value.x + sourceHandle.value.width / 2 : sourceNode.value?.__rf.width / 2
);
const sourceHandleY = computed(() =>
sourceHandle.value ? sourceHandle.value.y + sourceHandle.value.height / 2 : sourceNode.value?.__rf.height
);
const sourceX = computed(() => sourceNode.value?.__rf.position.x + sourceHandleX.value);
const sourceY = computed(() => sourceNode.value?.__rf.position.y + sourceHandleY.value);
const targetX = (props.connectionPositionX - props.transform[0]) / props.transform[2]; const targetX = computed(() => (props.connectionPositionX - props.transform[0]) / props.transform[2]);
const targetY = (props.connectionPositionY - props.transform[1]) / props.transform[2]; const targetY = computed(() => (props.connectionPositionY - props.transform[1]) / props.transform[2]);
const isRightOrLeft = sourceHandle?.position === Position.Left || sourceHandle?.position === Position.Right; const isRightOrLeft = computed(
const targetPosition = isRightOrLeft ? Position.Left : Position.Top; () => sourceHandle.value?.position === Position.Left || sourceHandle.value?.position === Position.Right
);
const targetPosition = computed(() => (isRightOrLeft.value ? Position.Left : Position.Top));
if (props.CustomConnectionLineComponent) { if (props.CustomConnectionLineComponent) {
// eslint-disable-next-line vue/no-setup-props-destructure
const ConnectionLineComponent: any = props.CustomConnectionLineComponent;
return () => ( return () => (
<g class="react-flow__connection"> <g class="react-flow__connection">
<component <ConnectionLineComponent
is={props.CustomConnectionLineComponent} sourceX={sourceX.value}
sourceX={sourceX} sourceY={sourceY.value}
sourceY={sourceY} sourcePosition={sourceHandle.value?.position}
sourcePosition={sourceHandle?.position} targetX={targetX.value}
targetX={targetX} targetY={targetY.value}
targetY={targetY} targetPosition={targetPosition.value}
targetPosition={targetPosition}
connectionLineType={props.connectionLineType} connectionLineType={props.connectionLineType}
connectionLineStyle={props.connectionLineStyle} connectionLineStyle={props.connectionLineStyle}
/> />
@@ -124,43 +132,47 @@ const ConnectionLine = defineComponent({
); );
} }
let dAttr = ''; let dAttr = computed(() => `M${sourceX.value},${sourceY.value} ${targetX.value},${targetY.value}`);
if (props.connectionLineType === ConnectionLineType.Bezier) { if (props.connectionLineType === ConnectionLineType.Bezier) {
dAttr = getBezierPath({ dAttr = computed(() =>
sourceX, getBezierPath({
sourceY, sourceX: sourceX.value,
sourcePosition: sourceHandle?.position, sourceY: sourceY.value,
targetX, sourcePosition: sourceHandle.value?.position,
targetY, targetX: targetX.value,
targetPosition targetY: targetY.value,
}); targetPosition: targetPosition.value
})
);
} else if (props.connectionLineType === ConnectionLineType.Step) { } else if (props.connectionLineType === ConnectionLineType.Step) {
dAttr = getSmoothStepPath({ dAttr = computed(() =>
sourceX, getSmoothStepPath({
sourceY, sourceX: sourceX.value,
sourcePosition: sourceHandle?.position, sourceY: sourceY.value,
targetX, sourcePosition: sourceHandle.value?.position,
targetY, targetX: targetX.value,
targetPosition, targetY: targetY.value,
borderRadius: 0 targetPosition: targetPosition.value,
}); borderRadius: 0
})
);
} else if (props.connectionLineType === ConnectionLineType.SmoothStep) { } else if (props.connectionLineType === ConnectionLineType.SmoothStep) {
dAttr = getSmoothStepPath({ dAttr = computed(() =>
sourceX, getSmoothStepPath({
sourceY, sourceX: sourceX.value,
sourcePosition: sourceHandle?.position, sourceY: sourceY.value,
targetX, sourcePosition: sourceHandle.value?.position,
targetY, targetX: targetX.value,
targetPosition targetY: targetY.value,
}); targetPosition: targetPosition.value
} else { })
dAttr = `M${sourceX},${sourceY} ${targetX},${targetY}`; );
} }
return () => ( return () => (
<g class="react-flow__connection"> <g class="react-flow__connection">
<path d={dAttr} class="react-flow__connection-path" style={props.connectionLineStyle} /> <path d={dAttr.value} class="react-flow__connection-path" style={props.connectionLineStyle} />
</g> </g>
); );
} }
-2
View File
@@ -120,7 +120,6 @@ const BezierEdge = defineComponent({
} }
}, },
setup(props) { setup(props) {
console.log('edge');
const centered = computed(() => { const centered = computed(() => {
return getCenter({ return getCenter({
sourceX: props.sourceX, sourceX: props.sourceX,
@@ -132,7 +131,6 @@ const BezierEdge = defineComponent({
}); });
}); });
const path = computed(() => { const path = computed(() => {
console.log('computing in edge');
return getBezierPath({ return getBezierPath({
sourceX: props.sourceX, sourceX: props.sourceX,
sourceY: props.sourceY, sourceY: props.sourceY,
+5 -5
View File
@@ -48,23 +48,23 @@ export default (EdgeComponent: any): Component<EdgeProps> => {
pinia.addSelectedElements(edgeElement.value as any); pinia.addSelectedElements(edgeElement.value as any);
} }
props.onClick?.(event, edgeElement.value); if (props.onClick) props.onClick?.(event, edgeElement.value);
}; };
const onEdgeContextMenu = (event: MouseEvent) => { const onEdgeContextMenu = (event: MouseEvent) => {
props.onContextMenu?.(event, edgeElement.value); if (props.onContextMenu) props.onContextMenu?.(event, edgeElement.value);
}; };
const onEdgeMouseEnter = (event: MouseEvent) => { const onEdgeMouseEnter = (event: MouseEvent) => {
props.onMouseEnter?.(event, edgeElement.value); if (props.onMouseEnter) props.onMouseEnter?.(event, edgeElement.value);
}; };
const onEdgeMouseMove = (event: MouseEvent) => { const onEdgeMouseMove = (event: MouseEvent) => {
props.onMouseMove?.(event, edgeElement.value); if (props.onMouseMove) props.onMouseMove?.(event, edgeElement.value);
}; };
const onEdgeMouseLeave = (event: MouseEvent) => { const onEdgeMouseLeave = (event: MouseEvent) => {
props.onMouseLeave?.(event, edgeElement.value); if (props.onMouseLeave) props.onMouseLeave?.(event, edgeElement.value);
}; };
const handleEdgeUpdater = (event: MouseEvent, isSourceHandle: boolean) => { const handleEdgeUpdater = (event: MouseEvent, isSourceHandle: boolean) => {
-2
View File
@@ -103,8 +103,6 @@ export function onMouseDown(
// when react-flow is used inside a shadow root we can't use document // when react-flow is used inside a shadow root we can't use document
const doc = getHostForElement(event.target as HTMLElement); const doc = getHostForElement(event.target as HTMLElement);
console.log(doc);
if (!doc) { if (!doc) {
return; return;
} }
+2 -4
View File
@@ -1,5 +1,4 @@
import { Connection, ElementId, Position } from '../../types'; import { Connection, ElementId, Position } from '../../types';
import { onMouseDown, ValidConnectionFunc } from './handler'; import { onMouseDown, ValidConnectionFunc } from './handler';
import { defineComponent, inject, PropType } from 'vue'; import { defineComponent, inject, PropType } from 'vue';
import store from '../../store'; import store from '../../store';
@@ -42,7 +41,6 @@ const Handle = defineComponent({
setup(props, { slots }) { setup(props, { slots }) {
const pinia = store(); const pinia = store();
const nodeId = inject<ElementId>('NodeIdContext') as ElementId; const nodeId = inject<ElementId>('NodeIdContext') as ElementId;
const handleId = props.id || null;
const isTarget = props.type === 'target'; const isTarget = props.type === 'target';
const onConnectExtended = (params: Connection) => { const onConnectExtended = (params: Connection) => {
@@ -53,7 +51,7 @@ const Handle = defineComponent({
const onMouseDownHandler = (event: MouseEvent) => { const onMouseDownHandler = (event: MouseEvent) => {
onMouseDown( onMouseDown(
event, event,
handleId, props.id || '',
nodeId, nodeId,
pinia.setConnectionNodeId, pinia.setConnectionNodeId,
pinia.setConnectionPosition, pinia.setConnectionPosition,
@@ -82,7 +80,7 @@ const Handle = defineComponent({
return () => ( return () => (
<div <div
data-handleid={handleId} data-handleid={props.id}
data-nodeid={nodeId} data-nodeid={nodeId}
data-handlepos={props.position} data-handlepos={props.position}
class={handleClasses} class={handleClasses}
-1
View File
@@ -93,7 +93,6 @@ export const getEdgePositions = (
const sourceHandlePos = getHandlePosition(sourcePosition, sourceNode, sourceHandle); const sourceHandlePos = getHandlePosition(sourcePosition, sourceNode, sourceHandle);
const targetHandlePos = getHandlePosition(targetPosition, targetNode, targetHandle); const targetHandlePos = getHandlePosition(targetPosition, targetNode, targetHandle);
console.log('getting edge positions');
return { return {
sourceX: sourceHandlePos.x, sourceX: sourceHandlePos.x,
sourceY: sourceHandlePos.y, sourceY: sourceHandlePos.y,
-2
View File
@@ -2,9 +2,7 @@ import FlowRenderer from '../FlowRenderer';
import NodeRenderer from '../NodeRenderer'; import NodeRenderer from '../NodeRenderer';
import EdgeRenderer from '../EdgeRenderer'; import EdgeRenderer from '../EdgeRenderer';
import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph'; import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph';
import { ReactFlowProps } from '../RevueFlow'; import { ReactFlowProps } from '../RevueFlow';
import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode } from '../../types'; import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode } from '../../types';
import { CSSProperties, defineComponent, onMounted, PropType, ref } from 'vue'; import { CSSProperties, defineComponent, onMounted, PropType, ref } from 'vue';
import store from '../../store'; import store from '../../store';