feat(edges): add Bezier Edge

This commit is contained in:
moklick
2019-07-25 15:46:45 +02:00
parent bfeefd51b2
commit d094f5f312
7 changed files with 85 additions and 42 deletions
+43 -27
View File
@@ -30248,7 +30248,7 @@
}; };
} }
var UserSelection = (function () { var UserSelection = React.memo(function () {
var selectionPane = React.useRef(null); var selectionPane = React.useRef(null);
var _useState = React.useState(initialRect), var _useState = React.useState(initialRect),
@@ -32554,7 +32554,7 @@
}, {}); }, {});
} }
var NodesSelection = (function () { var NodesSelection = React.memo(function () {
var graphContext = React.useContext(GraphContext); var graphContext = React.useContext(GraphContext);
var _useState = React.useState({ var _useState = React.useState({
@@ -32581,12 +32581,12 @@
var position = state.selectedNodesBbox; var position = state.selectedNodesBbox;
var onStart = function onStart(evt) { var onStart = function onStart(evt) {
var scaledClientX = { var scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
var offsetX = scaledClientX.x - position.x - x; var offsetX = scaledClient.x - position.x - x;
var offsetY = scaledClientX.y - position.y - y; var offsetY = scaledClient.y - position.y - y;
var startPositions = getStartPositions(state.selectedElements); var startPositions = getStartPositions(state.selectedElements);
setOffset({ setOffset({
x: offsetX, x: offsetX,
@@ -32596,14 +32596,14 @@
}; };
var onDrag = function onDrag(evt) { var onDrag = function onDrag(evt) {
var scaledClientX = { var scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
state.selectedElements.filter(isNode).forEach(function (node) { state.selectedElements.filter(isNode).forEach(function (node) {
dispatch(updateNodePos(node.data.id, { dispatch(updateNodePos(node.data.id, {
x: startPositions[node.data.id].x + scaledClientX.x - position.x - offset.x - x, x: startPositions[node.data.id].x + scaledClient.x - position.x - offset.x - x,
y: startPositions[node.data.id].y + scaledClientX.y - position.y - offset.y - y y: startPositions[node.data.id].y + scaledClient.y - position.y - offset.y - y
})); }));
}); });
}; };
@@ -32662,8 +32662,7 @@
} }
var d3ZoomInstance = zoom().scaleExtent([0.5, 2]); var d3ZoomInstance = zoom().scaleExtent([0.5, 2]);
var GraphView = React.memo(function (props) {
var GraphView = function GraphView(props) {
var zoomPane = React.useRef(null); var zoomPane = React.useRef(null);
var _useContext = React.useContext(GraphContext), var _useContext = React.useContext(GraphContext),
@@ -32735,13 +32734,12 @@
}, },
ref: zoomPane ref: zoomPane
})); }));
}; });
var GraphView$1 = reactSizeme.withSize({ var GraphView$1 = reactSizeme.withSize({
monitorHeight: true monitorHeight: true
})(GraphView); })(GraphView);
var GlobalKeyHandler = (function (props) { var GlobalKeyHandler = React.memo(function (props) {
var _useContext = React.useContext(GraphContext), var _useContext = React.useContext(GraphContext),
state = _useContext.state, state = _useContext.state,
dispatch = _useContext.dispatch; dispatch = _useContext.dispatch;
@@ -32888,7 +32886,7 @@
}; };
var wrapNode = (function (NodeComponent) { var wrapNode = (function (NodeComponent) {
return function (props) { return React.memo(function (props) {
var nodeElement = React.useRef(null); var nodeElement = React.useRef(null);
var _useContext = React.useContext(GraphContext), var _useContext = React.useContext(GraphContext),
@@ -32937,12 +32935,12 @@
return false; return false;
} }
var scaledClientX = { var scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
var offsetX = scaledClientX.x - position.x - x; var offsetX = scaledClient.x - position.x - x;
var offsetY = scaledClientX.y - position.y - y; var offsetY = scaledClient.y - position.y - y;
setOffset({ setOffset({
x: offsetX, x: offsetX,
y: offsetY y: offsetY
@@ -32950,13 +32948,13 @@
}; };
var onDrag = function onDrag(evt) { var onDrag = function onDrag(evt) {
var scaledClientX = { var scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
dispatch(updateNodePos(id, { dispatch(updateNodePos(id, {
x: scaledClientX.x - x - offset.x, x: scaledClient.x - x - offset.x,
y: scaledClientX.y - y - offset.y y: scaledClient.y - y - offset.y
})); }));
}; };
@@ -32988,7 +32986,7 @@
}, },
onClick: onNodeClick onClick: onNodeClick
}, React__default.createElement(NodeComponent, props))); }, React__default.createElement(NodeComponent, props)));
}; });
}); });
function createNodeTypes(nodeTypes) { function createNodeTypes(nodeTypes) {
@@ -33009,13 +33007,30 @@
var DefaultEdge = (function (props) { var DefaultEdge = (function (props) {
var targetNode = props.targetNode, var targetNode = props.targetNode,
sourceNode = props.sourceNode; sourceNode = props.sourceNode;
var style = props.data ? props.data.style : {};
var sourceX = sourceNode.__rg.position.x + sourceNode.__rg.width / 2; var sourceX = sourceNode.__rg.position.x + sourceNode.__rg.width / 2;
var sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height; var sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height;
var targetX = targetNode.__rg.position.x + targetNode.__rg.width / 2; var targetX = targetNode.__rg.position.x + targetNode.__rg.width / 2;
var targetY = targetNode.__rg.position.y; var targetY = targetNode.__rg.position.y;
return React__default.createElement("path", { return React__default.createElement("path", _extends({}, style, {
d: "M ".concat(sourceX, ",").concat(sourceY, "L ").concat(targetX, ",").concat(targetY) d: "M ".concat(sourceX, ",").concat(sourceY, "L ").concat(targetX, ",").concat(targetY)
}); }));
});
var BezierEdge = (function (props) {
var targetNode = props.targetNode,
sourceNode = props.sourceNode;
var style = props.data ? props.data.style : {};
var sourceX = sourceNode.__rg.position.x + sourceNode.__rg.width / 2;
var sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height;
var targetX = targetNode.__rg.position.x + targetNode.__rg.width / 2;
var targetY = targetNode.__rg.position.y;
var yOffset = Math.abs(targetY - sourceY) / 2;
var centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
var dAttr = "M".concat(sourceX, ",").concat(sourceY, " C").concat(sourceX, ",").concat(centerY, " ").concat(targetX, ",").concat(centerY, " ").concat(targetX, ",").concat(targetY);
return React__default.createElement("path", _extends({}, style, {
d: dAttr
}));
}); });
var isInputTarget$1 = function isInputTarget(e) { var isInputTarget$1 = function isInputTarget(e) {
@@ -33023,7 +33038,7 @@
}; };
var wrapEdge = (function (EdgeComponent) { var wrapEdge = (function (EdgeComponent) {
return function (props) { return React.memo(function (props) {
var _useContext = React.useContext(GraphContext), var _useContext = React.useContext(GraphContext),
state = _useContext.state, state = _useContext.state,
dispatch = _useContext.dispatch; dispatch = _useContext.dispatch;
@@ -33054,15 +33069,16 @@
}); });
} }
}, React__default.createElement(EdgeComponent, props)); }, React__default.createElement(EdgeComponent, props));
}; });
}); });
function createEdgeTypes(edgeTypes) { function createEdgeTypes(edgeTypes) {
var standardTypes = { var standardTypes = {
"default": wrapEdge(edgeTypes["default"] || DefaultEdge) "default": wrapEdge(edgeTypes["default"] || DefaultEdge),
bezier: wrapEdge(edgeTypes.bezier || BezierEdge)
}; };
var specialTypes = Object.keys(DefaultEdge).filter(function (k) { var specialTypes = Object.keys(DefaultEdge).filter(function (k) {
return !['default'].includes(k); return !['default', 'bezier'].includes(k);
}).reduce(function (res, key) { }).reduce(function (res, key) {
res[key] = wrapEdge(nodeTypes[key] || DefaultEdge); res[key] = wrapEdge(nodeTypes[key] || DefaultEdge);
return res; return res;
+1 -1
View File
@@ -41,7 +41,7 @@ class App extends PureComponent {
{ data: { id: '4', label: 'nody nodes', type: 'output' }, position: { x: 50, y: 300 } }, { data: { id: '4', label: 'nody nodes', type: 'output' }, position: { x: 50, y: 300 } },
{ data: { id: '5', label: 'Another node', type: 'default' }, position: { x: 400, y: 300 } }, { data: { id: '5', label: 'Another node', type: 'default' }, position: { x: 400, y: 300 } },
{ data: { id: '6', label: 'no option selected', type: 'special', onChange }, position: { x: 400, y: 400 } }, { data: { id: '6', label: 'no option selected', type: 'special', onChange }, position: { x: 400, y: 400 } },
{ data: { source: '1', target: '2' } }, { data: { source: '1', target: '2', type: 'bezier', style: { stroke: 'orange' } } },
{ data: { source: '2', target: '3' } }, { data: { source: '2', target: '3' } },
{ data: { source: '3', target: '4' } }, { data: { source: '3', target: '4' } },
{ data: { source: '3', target: '5' } }, { data: { source: '3', target: '5' } },
+23
View File
@@ -0,0 +1,23 @@
import React from 'react';
export default (props) => {
const { targetNode, sourceNode } = props;
const style = props.data ? props.data.style : {};
const sourceX = sourceNode.__rg.position.x + (sourceNode.__rg.width / 2);
const sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height;
const targetX = targetNode.__rg.position.x + (targetNode.__rg.width / 2);
const targetY = targetNode.__rg.position.y;
const yOffset = Math.abs(targetY - sourceY) / 2;
const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
const dAttr = `M${sourceX},${sourceY} C${sourceX},${centerY} ${targetX},${centerY} ${targetX},${targetY}`;
return (
<path
{...style}
d={dAttr}
/>
);
};
@@ -2,6 +2,7 @@ import React from 'react';
export default (props) => { export default (props) => {
const { targetNode, sourceNode } = props; const { targetNode, sourceNode } = props;
const style = props.data ? props.data.style : {};
const sourceX = sourceNode.__rg.position.x + (sourceNode.__rg.width / 2); const sourceX = sourceNode.__rg.position.x + (sourceNode.__rg.width / 2);
const sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height; const sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height;
@@ -11,6 +12,7 @@ export default (props) => {
return ( return (
<path <path
{...style}
d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`} d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`}
/> />
); );
+3 -1
View File
@@ -1,14 +1,16 @@
import DefaultEdge from './EdgeTypes/DefaultEdge'; import DefaultEdge from './EdgeTypes/DefaultEdge';
import BezierEdge from './EdgeTypes/BezierEdge';
import wrapEdge from './EdgeTypes/wrapEdge'; import wrapEdge from './EdgeTypes/wrapEdge';
export function createEdgeTypes(edgeTypes) { export function createEdgeTypes(edgeTypes) {
const standardTypes = { const standardTypes = {
default: wrapEdge(edgeTypes.default || DefaultEdge), default: wrapEdge(edgeTypes.default || DefaultEdge),
bezier: wrapEdge(edgeTypes.bezier || BezierEdge)
}; };
const specialTypes = Object const specialTypes = Object
.keys(DefaultEdge) .keys(DefaultEdge)
.filter(k => !['default'].includes(k)) .filter(k => !['default', 'bezier'].includes(k))
.reduce((res, key) => { .reduce((res, key) => {
res[key] = wrapEdge(nodeTypes[key] || DefaultEdge); res[key] = wrapEdge(nodeTypes[key] || DefaultEdge);
+6 -6
View File
@@ -33,25 +33,25 @@ export default NodeComponent => memo((props) => {
return false; return false;
} }
const scaledClientX = { const scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
} }
const offsetX = scaledClientX.x - position.x - x; const offsetX = scaledClient.x - position.x - x;
const offsetY = scaledClientX.y - position.y - y; const offsetY = scaledClient.y - position.y - y;
setOffset({ x: offsetX, y: offsetY }); setOffset({ x: offsetX, y: offsetY });
}; };
const onDrag = (evt) => { const onDrag = (evt) => {
const scaledClientX = { const scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
dispatch(updateNodePos(id, { dispatch(updateNodePos(id, {
x: scaledClientX.x - x - offset.x, x: scaledClient.x - x - offset.x,
y: scaledClientX.y - y - offset.y y: scaledClient.y - y - offset.y
})); }));
}; };
+7 -7
View File
@@ -1,4 +1,4 @@
import React, { useContext, useState, memo } from 'react'; import React, { useContext, useState, useCallback, memo } from 'react';
import ReactDraggable from 'react-draggable'; import ReactDraggable from 'react-draggable';
import { GraphContext } from '../GraphContext'; import { GraphContext } from '../GraphContext';
@@ -29,12 +29,12 @@ export default memo(() => {
const position = state.selectedNodesBbox; const position = state.selectedNodesBbox;
const onStart = (evt) => { const onStart = (evt) => {
const scaledClientX = { const scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
const offsetX = scaledClientX.x - position.x - x; const offsetX = scaledClient.x - position.x - x;
const offsetY = scaledClientX.y - position.y - y; const offsetY = scaledClient.y - position.y - y;
const startPositions = getStartPositions(state.selectedElements); const startPositions = getStartPositions(state.selectedElements);
setOffset({ x: offsetX, y: offsetY }); setOffset({ x: offsetX, y: offsetY });
@@ -42,15 +42,15 @@ export default memo(() => {
}; };
const onDrag = (evt) => { const onDrag = (evt) => {
const scaledClientX = { const scaledClient = {
x: evt.clientX * (1 / k), x: evt.clientX * (1 / k),
y: evt.clientY * (1 / k) y: evt.clientY * (1 / k)
}; };
state.selectedElements.filter(isNode).forEach(node => { state.selectedElements.filter(isNode).forEach(node => {
dispatch(updateNodePos(node.data.id, { dispatch(updateNodePos(node.data.id, {
x: startPositions[node.data.id].x + scaledClientX.x - position.x - offset.x - x , x: startPositions[node.data.id].x + scaledClient.x - position.x - offset.x - x ,
y: startPositions[node.data.id].y + scaledClientX.y - position.y - offset.y - y y: startPositions[node.data.id].y + scaledClient.y - position.y - offset.y - y
})); }));
}); });
}; };