Skip to content

Commit 90d3247

Browse files
committed
Better reference file node ordering
1 parent 675c2ed commit 90d3247

16 files changed

+1549
-205
lines changed

babel.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ module.exports = function(api){
1212
"@babel/plugin-proposal-class-properties",
1313
"babel-plugin-minify-dead-code-elimination"
1414
],
15-
"comments": false
15+
"comments": true
1616
};
1717
};

demo/demo-compiled.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/react-workflow-viz.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/react-workflow-viz.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/react-workflow-viz.node.js

Lines changed: 753 additions & 95 deletions
Large diffs are not rendered by default.

dist/react-workflow-viz.node.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

es/components/Edge.js

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,20 @@ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || func
5252
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
5353

5454
var pathDimensionFunctions = {
55+
/**
56+
* Draw a bezier path from startPt to endPt.
57+
*
58+
* @param {Object} startPt - Object with x and y coordinates.
59+
* @param {Object} endPt - Object with x and y coordinates.
60+
* @param {Number[]} [ledgeWidths] - Little widths of line right before/after node. To allow for horizontal arrow.
61+
* @returns {string} 'd' attribute value for an SVG path.
62+
*/
5563
'drawBezierEdge': function drawBezierEdge(startPt, endPt, columnSpacing, rowSpacing, nodeEdgeLedgeWidths) {
5664
var ledgeWidths = nodeEdgeLedgeWidths;
5765
var path = d3.path();
5866
path.moveTo(startPt.x, startPt.y);
59-
path.lineTo(startPt.x + ledgeWidths[0], startPt.y);
67+
path.lineTo(startPt.x + ledgeWidths[0], startPt.y); // First ledge
68+
6069
var nodeXDif = Math.abs(endPt.x - startPt.x);
6170
var bezierStartPt = {
6271
'x': startPt.x + ledgeWidths[0],
@@ -67,8 +76,11 @@ var pathDimensionFunctions = {
6776
'y': endPt.y
6877
};
6978

70-
if (nodeXDif > columnSpacing) {
71-
bezierStartPt.x += Math.max(0, nodeXDif - columnSpacing * (Math.abs(endPt.y - startPt.y) / rowSpacing * 2.5));
79+
if (nodeXDif > columnSpacing
80+
/* && Math.abs(endPt.y - startPt.y) <= this.props.rowSpacing * 2*/
81+
) {
82+
// Draw straight line until last section. Length depending on how close together y-axes are (revert to default bezier if far apart).
83+
bezierStartPt.x += Math.max(0, nodeXDif - columnSpacing * (Math.abs(endPt.y - startPt.y) / rowSpacing * 2.5)); //path.lineTo(bezierStartPt.x, bezierStartPt.y);
7284
}
7385

7486
var bezierXDif = Math.abs(bezierStartPt.x - bezierEndPt.x);
@@ -81,13 +93,18 @@ var pathDimensionFunctions = {
8193
}];
8294

8395
if (startPt.x > endPt.x) {
96+
// Our input edge appears AFTER the target.
97+
//var dif = Math.min(1, 5 / Math.max(1, Math.abs(endPt.y - startPt.y) )) * (this.props.rowSpacing || 75);
8498
var dif = Math.max(rowSpacing || 75);
8599
controlPoints[0].y += dif * (endPt.y >= startPt.y ? 1 : -1);
86100
controlPoints[1].y += dif * (endPt.y - startPt.y > rowSpacing ? -1 : 1);
87101
controlPoints[1].x = endPt.x - Math.abs(endPt.x - startPt.x) * .5;
88102
}
89103

90-
path.bezierCurveTo(controlPoints[0].x, controlPoints[0].y, controlPoints[1].x, controlPoints[1].y, bezierEndPt.x, endPt.y);
104+
path.bezierCurveTo(controlPoints[0].x, controlPoints[0].y, // - pathAscend,
105+
controlPoints[1].x, controlPoints[1].y, // + pathAscend,
106+
bezierEndPt.x, endPt.y); // Final ledge
107+
91108
path.lineTo(endPt.x, endPt.y);
92109
return path.toString();
93110
},
@@ -120,15 +137,21 @@ var pathDimensionFunctions = {
120137
adjVertices[adjVertices.length - 2][0] -= nodeEdgeLedgeWidths[0];
121138
}
122139

123-
adjVertices[0][0] = startPt && startPt.x || adjVertices[0][0];
124-
adjVertices[adjVertices.length - 1][0] = endPt && endPt.x || adjVertices[adjVertices.length - 1][0];
140+
adjVertices[0][0] = startPt && startPt.x || adjVertices[0][0]; // + nodeEdgeLedgeWidths[0];
141+
142+
adjVertices[adjVertices.length - 1][0] = endPt && endPt.x || adjVertices[adjVertices.length - 1][0]; // - nodeEdgeLedgeWidths[1];
143+
125144
var lineGenFxn = d3.line().x(function (d) {
126145
return d[0];
127146
}).y(function (d) {
128147
return d[1];
129148
}).curve(d3.curveMonotoneX);
130149
return lineGenFxn(adjVertices);
131150
},
151+
152+
/**
153+
* @deprecated
154+
*/
132155
'drawStraightEdge': function drawStraightEdge(startPt, endPt) {
133156
var path = d3.path();
134157
path.moveTo(startPt.x, startPt.y);
@@ -139,7 +162,9 @@ var pathDimensionFunctions = {
139162
};
140163
exports.pathDimensionFunctions = pathDimensionFunctions;
141164

142-
var Edge = function (_React$Component) {
165+
var Edge =
166+
/*#__PURE__*/
167+
function (_React$Component) {
143168
_inherits(Edge, _React$Component);
144169

145170
_createClass(Edge, null, [{
@@ -150,7 +175,11 @@ var Edge = function (_React$Component) {
150175
}, {
151176
key: "isRelated",
152177
value: function isRelated(edge, selectedNode) {
153-
return _Node["default"].isRelated(edge.source, selectedNode);
178+
return _Node["default"].isRelated(edge.source, selectedNode); // Enable the following later _if_ we go beyond 1 input node deep.
179+
//return (
180+
// Node.isRelated(edge.source, selectedNode) ||
181+
// Node.isRelated(edge.target, selectedNode)
182+
//);
154183
}
155184
}, {
156185
key: "isDistantlySelected",
@@ -250,7 +279,9 @@ var Edge = function (_React$Component) {
250279

251280
_this = _possibleConstructorReturn(this, _getPrototypeOf(Edge).call(this, props));
252281
_this.generatePathDimension = _this.generatePathDimension.bind(_assertThisInitialized(_this));
253-
_this.transitionPathDimensions = _this.transitionPathDimensions.bind(_assertThisInitialized(_this));
282+
_this.transitionPathDimensions = _this.transitionPathDimensions.bind(_assertThisInitialized(_this)); // Create own memoized copy/instance of intensive static functions.
283+
// Otherwise if left static, will be re-ran each time as many edges call it.
284+
254285
_this.memoized = {
255286
isDistantlySelected: (0, _memoizeOne["default"])(Edge.isDistantlySelected),
256287
isRelated: (0, _memoizeOne["default"])(Edge.isRelated),
@@ -265,7 +296,9 @@ var Edge = function (_React$Component) {
265296
_this.getComputedProperties = _this.getComputedProperties.bind(_assertThisInitialized(_this));
266297
_this.state = {
267298
'pathDimension': _this.generatePathDimension()
268-
};
299+
}; // Alternative implementation of transition -
300+
// adjust pathRef.current `d` attribute manually
301+
269302
_this.pathRef = _react["default"].createRef();
270303
return _this;
271304
}
@@ -297,6 +330,11 @@ var Edge = function (_React$Component) {
297330
distantlySelected: distantlySelected
298331
};
299332
}
333+
/**
334+
* If any of our nodes' coordinates have updated, update state.pathDimension either via a D3 animation tween acting on setState or instantly via setState.
335+
* Whether instant or gradual dimension update is based on result of `this.shouldDoTransitionOfEdge()` : boolean
336+
*/
337+
300338
}, {
301339
key: "componentDidUpdate",
302340
value: function componentDidUpdate(pastProps) {
@@ -309,20 +347,25 @@ var Edge = function (_React$Component) {
309347

310348
if (Edge.didNodeCoordinatesChange(this.props, pastProps)) {
311349
if (!this.shouldDoTransitionOfEdge()) {
350+
// Instant
312351
this.setState({
313352
'pathDimension': this.generatePathDimension()
314353
});
315354
} else {
355+
// Animate
316356
var startEndPtCoords = [{
317357
'x': pastProps.startX,
318358
'y': pastProps.startY
319-
}, {
359+
}, // StartA
360+
{
320361
'x': startX,
321362
'y': startY
322-
}, {
363+
}, // StartB
364+
{
323365
'x': pastProps.endX,
324366
'y': pastProps.endY
325-
}, {
367+
}, // StartA
368+
{
326369
'x': endX,
327370
'y': endY
328371
}];
@@ -334,6 +377,7 @@ var Edge = function (_React$Component) {
334377
}
335378
}
336379
} else if (!_underscore["default"].isEqual(this.getPathOffsets(), this.getPathOffsets(pastProps))) {
380+
// Instant
337381
this.setState({
338382
'pathDimension': this.generatePathDimension()
339383
});
@@ -359,18 +403,35 @@ var Edge = function (_React$Component) {
359403
if (this.props[propKeys[i]] !== nextProps[propKeys[i]]) {
360404
return true;
361405
}
362-
}
406+
} // If state.pathDimension changes we _do not_ update, since DOM elements should already be transitioned.
407+
363408

364409
return false;
365410
}
366411
}, {
367412
key: "shouldDoTransitionOfEdge",
368413
value: function shouldDoTransitionOfEdge() {
369414
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
370-
if (props.noTransition) return false;
415+
if (props.noTransition) return false; // Until we adjust all Edges to transition within a single DOM update/redraw,
416+
// we optimize by not transitioning unless <= 50 edges.
417+
// This is because each Edge currently launches own transition
418+
// which cascades into an exponential number of transitions/viewport-updates.
419+
371420
if (props.edgeCount > 60) return false;
372421
return true;
373422
}
423+
/**
424+
* Transitions edge dimensions over time.
425+
* Updates `state.pathDimension` incrementally using d3.transition().
426+
*
427+
* @todo
428+
* In future, all transitions could be done in `EdgesLayer` instead of `Edge`,
429+
* this would allow us to batch all the DOM updates into a single function wrapped
430+
* in a `requestAnimationFrame` call. This will require some dynamic programming as
431+
* well as caching of ege:node-coords to detect changes and run transitions.
432+
* The changeTween itself should transition _all_ Edges that need to be transitioned.
433+
*/
434+
374435
}, {
375436
key: "transitionPathDimensions",
376437
value: function transitionPathDimensions(startPtA, startPtB, endPtA, endPtB, startVertices, endVertices) {
@@ -388,7 +449,8 @@ var Edge = function (_React$Component) {
388449
});
389450
}
390451

391-
var pathElem = this.pathRef.current;
452+
var pathElem = this.pathRef.current; // Necessary if using alternate transition approach(es).
453+
392454
if (!pathElem) return;
393455
d3.select(this).interrupt().transition().ease(d3.easeQuadOut).duration(500).tween("changeDimension", function changeTween() {
394456
return function (t) {

0 commit comments

Comments
 (0)