force-graph 1.42.13 → 1.42.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/force-graph.common.js +182 -268
- package/dist/force-graph.js +209 -2477
- package/dist/force-graph.js.map +1 -1
- package/dist/force-graph.min.js +3 -3
- package/dist/force-graph.module.js +147 -224
- package/package.json +12 -12
- package/src/force-graph.css +0 -1
- package/src/force-graph.js +6 -0
|
@@ -15,27 +15,15 @@ var indexBy = require('index-array-by');
|
|
|
15
15
|
var d3Scale = require('d3-scale');
|
|
16
16
|
var d3ScaleChromatic = require('d3-scale-chromatic');
|
|
17
17
|
|
|
18
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
19
|
-
|
|
20
|
-
var throttle__default = /*#__PURE__*/_interopDefaultLegacy(throttle);
|
|
21
|
-
var TWEEN__default = /*#__PURE__*/_interopDefaultLegacy(TWEEN);
|
|
22
|
-
var Kapsule__default = /*#__PURE__*/_interopDefaultLegacy(Kapsule);
|
|
23
|
-
var accessorFn__default = /*#__PURE__*/_interopDefaultLegacy(accessorFn);
|
|
24
|
-
var ColorTracker__default = /*#__PURE__*/_interopDefaultLegacy(ColorTracker);
|
|
25
|
-
var indexBy__default = /*#__PURE__*/_interopDefaultLegacy(indexBy);
|
|
26
|
-
|
|
27
18
|
function styleInject(css, ref) {
|
|
28
19
|
if (ref === void 0) ref = {};
|
|
29
20
|
var insertAt = ref.insertAt;
|
|
30
|
-
|
|
31
21
|
if (!css || typeof document === 'undefined') {
|
|
32
22
|
return;
|
|
33
23
|
}
|
|
34
|
-
|
|
35
24
|
var head = document.head || document.getElementsByTagName('head')[0];
|
|
36
25
|
var style = document.createElement('style');
|
|
37
26
|
style.type = 'text/css';
|
|
38
|
-
|
|
39
27
|
if (insertAt === 'top') {
|
|
40
28
|
if (head.firstChild) {
|
|
41
29
|
head.insertBefore(style, head.firstChild);
|
|
@@ -45,7 +33,6 @@ function styleInject(css, ref) {
|
|
|
45
33
|
} else {
|
|
46
34
|
head.appendChild(style);
|
|
47
35
|
}
|
|
48
|
-
|
|
49
36
|
if (style.styleSheet) {
|
|
50
37
|
style.styleSheet.cssText = css;
|
|
51
38
|
} else {
|
|
@@ -53,22 +40,19 @@ function styleInject(css, ref) {
|
|
|
53
40
|
}
|
|
54
41
|
}
|
|
55
42
|
|
|
56
|
-
var css_248z = ".force-graph-container canvas {\n display: block;\n user-select: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n.force-graph-container .graph-tooltip {\n position: absolute;\n top: 0;\n
|
|
43
|
+
var css_248z = ".force-graph-container canvas {\n display: block;\n user-select: none;\n outline: none;\n -webkit-tap-highlight-color: transparent;\n}\n\n.force-graph-container .graph-tooltip {\n position: absolute;\n top: 0;\n font-family: sans-serif;\n font-size: 16px;\n padding: 4px;\n border-radius: 3px;\n color: #eee;\n background: rgba(0,0,0,0.65);\n visibility: hidden; /* by default */\n}\n\n.force-graph-container .clickable {\n cursor: pointer;\n}\n\n.force-graph-container .grabbable {\n cursor: move;\n cursor: grab;\n cursor: -moz-grab;\n cursor: -webkit-grab;\n}\n\n.force-graph-container .grabbable:active {\n cursor: grabbing;\n cursor: -moz-grabbing;\n cursor: -webkit-grabbing;\n}\n";
|
|
57
44
|
styleInject(css_248z);
|
|
58
45
|
|
|
59
46
|
function ownKeys(object, enumerableOnly) {
|
|
60
47
|
var keys = Object.keys(object);
|
|
61
|
-
|
|
62
48
|
if (Object.getOwnPropertySymbols) {
|
|
63
49
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
64
50
|
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
65
51
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
66
52
|
})), keys.push.apply(keys, symbols);
|
|
67
53
|
}
|
|
68
|
-
|
|
69
54
|
return keys;
|
|
70
55
|
}
|
|
71
|
-
|
|
72
56
|
function _objectSpread2(target) {
|
|
73
57
|
for (var i = 1; i < arguments.length; i++) {
|
|
74
58
|
var source = null != arguments[i] ? arguments[i] : {};
|
|
@@ -78,10 +62,8 @@ function _objectSpread2(target) {
|
|
|
78
62
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
79
63
|
});
|
|
80
64
|
}
|
|
81
|
-
|
|
82
65
|
return target;
|
|
83
66
|
}
|
|
84
|
-
|
|
85
67
|
function _typeof(obj) {
|
|
86
68
|
"@babel/helpers - typeof";
|
|
87
69
|
|
|
@@ -91,7 +73,6 @@ function _typeof(obj) {
|
|
|
91
73
|
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
92
74
|
}, _typeof(obj);
|
|
93
75
|
}
|
|
94
|
-
|
|
95
76
|
function _defineProperty(obj, key, value) {
|
|
96
77
|
if (key in obj) {
|
|
97
78
|
Object.defineProperty(obj, key, {
|
|
@@ -103,10 +84,8 @@ function _defineProperty(obj, key, value) {
|
|
|
103
84
|
} else {
|
|
104
85
|
obj[key] = value;
|
|
105
86
|
}
|
|
106
|
-
|
|
107
87
|
return obj;
|
|
108
88
|
}
|
|
109
|
-
|
|
110
89
|
function _setPrototypeOf(o, p) {
|
|
111
90
|
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
|
|
112
91
|
o.__proto__ = p;
|
|
@@ -114,12 +93,10 @@ function _setPrototypeOf(o, p) {
|
|
|
114
93
|
};
|
|
115
94
|
return _setPrototypeOf(o, p);
|
|
116
95
|
}
|
|
117
|
-
|
|
118
96
|
function _isNativeReflectConstruct() {
|
|
119
97
|
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
120
98
|
if (Reflect.construct.sham) return false;
|
|
121
99
|
if (typeof Proxy === "function") return true;
|
|
122
|
-
|
|
123
100
|
try {
|
|
124
101
|
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
125
102
|
return true;
|
|
@@ -127,7 +104,6 @@ function _isNativeReflectConstruct() {
|
|
|
127
104
|
return false;
|
|
128
105
|
}
|
|
129
106
|
}
|
|
130
|
-
|
|
131
107
|
function _construct(Parent, args, Class) {
|
|
132
108
|
if (_isNativeReflectConstruct()) {
|
|
133
109
|
_construct = Reflect.construct.bind();
|
|
@@ -141,44 +117,33 @@ function _construct(Parent, args, Class) {
|
|
|
141
117
|
return instance;
|
|
142
118
|
};
|
|
143
119
|
}
|
|
144
|
-
|
|
145
120
|
return _construct.apply(null, arguments);
|
|
146
121
|
}
|
|
147
|
-
|
|
148
122
|
function _slicedToArray(arr, i) {
|
|
149
123
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
150
124
|
}
|
|
151
|
-
|
|
152
125
|
function _toConsumableArray(arr) {
|
|
153
126
|
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
154
127
|
}
|
|
155
|
-
|
|
156
128
|
function _arrayWithoutHoles(arr) {
|
|
157
129
|
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
158
130
|
}
|
|
159
|
-
|
|
160
131
|
function _arrayWithHoles(arr) {
|
|
161
132
|
if (Array.isArray(arr)) return arr;
|
|
162
133
|
}
|
|
163
|
-
|
|
164
134
|
function _iterableToArray(iter) {
|
|
165
135
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
166
136
|
}
|
|
167
|
-
|
|
168
137
|
function _iterableToArrayLimit(arr, i) {
|
|
169
138
|
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
170
|
-
|
|
171
139
|
if (_i == null) return;
|
|
172
140
|
var _arr = [];
|
|
173
141
|
var _n = true;
|
|
174
142
|
var _d = false;
|
|
175
|
-
|
|
176
143
|
var _s, _e;
|
|
177
|
-
|
|
178
144
|
try {
|
|
179
145
|
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
|
|
180
146
|
_arr.push(_s.value);
|
|
181
|
-
|
|
182
147
|
if (i && _arr.length === i) break;
|
|
183
148
|
}
|
|
184
149
|
} catch (err) {
|
|
@@ -191,10 +156,8 @@ function _iterableToArrayLimit(arr, i) {
|
|
|
191
156
|
if (_d) throw _e;
|
|
192
157
|
}
|
|
193
158
|
}
|
|
194
|
-
|
|
195
159
|
return _arr;
|
|
196
160
|
}
|
|
197
|
-
|
|
198
161
|
function _unsupportedIterableToArray(o, minLen) {
|
|
199
162
|
if (!o) return;
|
|
200
163
|
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
@@ -203,27 +166,23 @@ function _unsupportedIterableToArray(o, minLen) {
|
|
|
203
166
|
if (n === "Map" || n === "Set") return Array.from(o);
|
|
204
167
|
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
205
168
|
}
|
|
206
|
-
|
|
207
169
|
function _arrayLikeToArray(arr, len) {
|
|
208
170
|
if (len == null || len > arr.length) len = arr.length;
|
|
209
|
-
|
|
210
171
|
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
211
|
-
|
|
212
172
|
return arr2;
|
|
213
173
|
}
|
|
214
|
-
|
|
215
174
|
function _nonIterableSpread() {
|
|
216
175
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
217
176
|
}
|
|
218
|
-
|
|
219
177
|
function _nonIterableRest() {
|
|
220
178
|
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
221
179
|
}
|
|
222
180
|
|
|
223
|
-
var autoColorScale = d3Scale.scaleOrdinal(d3ScaleChromatic.schemePaired);
|
|
181
|
+
var autoColorScale = d3Scale.scaleOrdinal(d3ScaleChromatic.schemePaired);
|
|
182
|
+
|
|
183
|
+
// Autoset attribute colorField by colorByAccessor property
|
|
224
184
|
// If an object has already a color, don't set it
|
|
225
185
|
// Objects can be nodes or links
|
|
226
|
-
|
|
227
186
|
function autoColorObjects(objects, colorByAccessor, colorField) {
|
|
228
187
|
if (!colorByAccessor || typeof colorField !== 'string') return;
|
|
229
188
|
objects.filter(function (obj) {
|
|
@@ -235,18 +194,16 @@ function autoColorObjects(objects, colorByAccessor, colorField) {
|
|
|
235
194
|
|
|
236
195
|
function getDagDepths (_ref, idAccessor) {
|
|
237
196
|
var nodes = _ref.nodes,
|
|
238
|
-
|
|
239
|
-
|
|
197
|
+
links = _ref.links;
|
|
240
198
|
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
199
|
+
_ref2$nodeFilter = _ref2.nodeFilter,
|
|
200
|
+
nodeFilter = _ref2$nodeFilter === void 0 ? function () {
|
|
201
|
+
return true;
|
|
202
|
+
} : _ref2$nodeFilter,
|
|
203
|
+
_ref2$onLoopError = _ref2.onLoopError,
|
|
204
|
+
onLoopError = _ref2$onLoopError === void 0 ? function (loopIds) {
|
|
205
|
+
throw "Invalid DAG structure! Found cycle in node path: ".concat(loopIds.join(' -> '), ".");
|
|
206
|
+
} : _ref2$onLoopError;
|
|
250
207
|
// linked graph
|
|
251
208
|
var graph = {};
|
|
252
209
|
nodes.forEach(function (node) {
|
|
@@ -259,7 +216,7 @@ function getDagDepths (_ref, idAccessor) {
|
|
|
259
216
|
});
|
|
260
217
|
links.forEach(function (_ref3) {
|
|
261
218
|
var source = _ref3.source,
|
|
262
|
-
|
|
219
|
+
target = _ref3.target;
|
|
263
220
|
var sourceId = getNodeId(source);
|
|
264
221
|
var targetId = getNodeId(target);
|
|
265
222
|
if (!graph.hasOwnProperty(sourceId)) throw "Missing source node with id: ".concat(sourceId);
|
|
@@ -267,7 +224,6 @@ function getDagDepths (_ref, idAccessor) {
|
|
|
267
224
|
var sourceNode = graph[sourceId];
|
|
268
225
|
var targetNode = graph[targetId];
|
|
269
226
|
sourceNode.out.push(targetNode);
|
|
270
|
-
|
|
271
227
|
function getNodeId(node) {
|
|
272
228
|
return _typeof(node) === 'object' ? idAccessor(node) : node;
|
|
273
229
|
}
|
|
@@ -276,31 +232,25 @@ function getDagDepths (_ref, idAccessor) {
|
|
|
276
232
|
traverse(Object.values(graph));
|
|
277
233
|
var nodeDepths = Object.assign.apply(Object, [{}].concat(_toConsumableArray(Object.entries(graph).filter(function (_ref4) {
|
|
278
234
|
var _ref5 = _slicedToArray(_ref4, 2),
|
|
279
|
-
|
|
280
|
-
|
|
235
|
+
node = _ref5[1];
|
|
281
236
|
return !node.skip;
|
|
282
237
|
}).map(function (_ref6) {
|
|
283
238
|
var _ref7 = _slicedToArray(_ref6, 2),
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
239
|
+
id = _ref7[0],
|
|
240
|
+
node = _ref7[1];
|
|
287
241
|
return _defineProperty({}, id, node.depth);
|
|
288
242
|
}))));
|
|
289
243
|
return nodeDepths;
|
|
290
|
-
|
|
291
244
|
function traverse(nodes) {
|
|
292
245
|
var nodeStack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
293
246
|
var currentDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
294
|
-
|
|
295
247
|
for (var i = 0, l = nodes.length; i < l; i++) {
|
|
296
248
|
var node = nodes[i];
|
|
297
|
-
|
|
298
249
|
if (nodeStack.indexOf(node) !== -1) {
|
|
299
250
|
var _ret = function () {
|
|
300
251
|
var loop = [].concat(_toConsumableArray(nodeStack.slice(nodeStack.indexOf(node))), [node]).map(function (d) {
|
|
301
252
|
return idAccessor(d.data);
|
|
302
253
|
});
|
|
303
|
-
|
|
304
254
|
if (!foundLoops.some(function (foundLoop) {
|
|
305
255
|
return foundLoop.length === loop.length && foundLoop.every(function (id, idx) {
|
|
306
256
|
return id === loop[idx];
|
|
@@ -309,13 +259,10 @@ function getDagDepths (_ref, idAccessor) {
|
|
|
309
259
|
foundLoops.push(loop);
|
|
310
260
|
onLoopError(loop);
|
|
311
261
|
}
|
|
312
|
-
|
|
313
262
|
return "continue";
|
|
314
263
|
}();
|
|
315
|
-
|
|
316
264
|
if (_ret === "continue") continue;
|
|
317
265
|
}
|
|
318
|
-
|
|
319
266
|
if (currentDepth > node.depth) {
|
|
320
267
|
// Don't unnecessarily revisit chunks of the graph
|
|
321
268
|
node.depth = currentDepth;
|
|
@@ -325,13 +272,15 @@ function getDagDepths (_ref, idAccessor) {
|
|
|
325
272
|
}
|
|
326
273
|
}
|
|
327
274
|
|
|
328
|
-
|
|
275
|
+
//
|
|
329
276
|
|
|
277
|
+
var DAG_LEVEL_NODE_RATIO = 2;
|
|
278
|
+
|
|
279
|
+
// whenever styling props are changed that require a canvas redraw
|
|
330
280
|
var notifyRedraw = function notifyRedraw(_, state) {
|
|
331
281
|
return state.onNeedsRedraw && state.onNeedsRedraw();
|
|
332
282
|
};
|
|
333
|
-
|
|
334
|
-
var CanvasForceGraph = Kapsule__default["default"]({
|
|
283
|
+
var CanvasForceGraph = Kapsule({
|
|
335
284
|
props: {
|
|
336
285
|
graphData: {
|
|
337
286
|
"default": {
|
|
@@ -341,7 +290,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
341
290
|
onChange: function onChange(_, state) {
|
|
342
291
|
state.engineRunning = false;
|
|
343
292
|
} // Pause simulation
|
|
344
|
-
|
|
345
293
|
},
|
|
346
294
|
dagMode: {
|
|
347
295
|
onChange: function onChange(dagMode, state) {
|
|
@@ -351,6 +299,7 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
351
299
|
}); // unfix nodes when disabling dag mode
|
|
352
300
|
}
|
|
353
301
|
},
|
|
302
|
+
|
|
354
303
|
dagLevelDistance: {},
|
|
355
304
|
dagNodeFilter: {
|
|
356
305
|
"default": function _default(node) {
|
|
@@ -544,7 +493,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
544
493
|
}
|
|
545
494
|
|
|
546
495
|
state.forceLayout.force(forceName, forceFn); // Force setter
|
|
547
|
-
|
|
548
496
|
return this;
|
|
549
497
|
},
|
|
550
498
|
d3ReheatSimulation: function d3ReheatSimulation(state) {
|
|
@@ -568,52 +516,49 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
568
516
|
!state.isShadow && paintArrows();
|
|
569
517
|
!state.isShadow && paintPhotons();
|
|
570
518
|
paintNodes();
|
|
571
|
-
return this;
|
|
519
|
+
return this;
|
|
520
|
+
|
|
521
|
+
//
|
|
572
522
|
|
|
573
523
|
function layoutTick() {
|
|
574
524
|
if (state.engineRunning) {
|
|
575
525
|
if (++state.cntTicks > state.cooldownTicks || new Date() - state.startTickTime > state.cooldownTime || state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin) {
|
|
576
526
|
state.engineRunning = false; // Stop ticking graph
|
|
577
|
-
|
|
578
527
|
state.onEngineStop();
|
|
579
528
|
} else {
|
|
580
529
|
state.forceLayout.tick(); // Tick it
|
|
581
|
-
|
|
582
530
|
state.onEngineTick();
|
|
583
531
|
}
|
|
584
532
|
}
|
|
585
533
|
}
|
|
586
|
-
|
|
587
534
|
function paintNodes() {
|
|
588
|
-
var getVisibility =
|
|
589
|
-
var getVal =
|
|
590
|
-
var getColor =
|
|
591
|
-
var getNodeCanvasObjectMode =
|
|
592
|
-
var ctx = state.ctx;
|
|
535
|
+
var getVisibility = accessorFn(state.nodeVisibility);
|
|
536
|
+
var getVal = accessorFn(state.nodeVal);
|
|
537
|
+
var getColor = accessorFn(state.nodeColor);
|
|
538
|
+
var getNodeCanvasObjectMode = accessorFn(state.nodeCanvasObjectMode);
|
|
539
|
+
var ctx = state.ctx;
|
|
593
540
|
|
|
541
|
+
// Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
|
|
594
542
|
var padAmount = state.isShadow / state.globalScale;
|
|
595
543
|
var visibleNodes = state.graphData.nodes.filter(getVisibility);
|
|
596
544
|
ctx.save();
|
|
597
545
|
visibleNodes.forEach(function (node) {
|
|
598
546
|
var nodeCanvasObjectMode = getNodeCanvasObjectMode(node);
|
|
599
|
-
|
|
600
547
|
if (state.nodeCanvasObject && (nodeCanvasObjectMode === 'before' || nodeCanvasObjectMode === 'replace')) {
|
|
601
548
|
// Custom node before/replace paint
|
|
602
549
|
state.nodeCanvasObject(node, ctx, state.globalScale);
|
|
603
|
-
|
|
604
550
|
if (nodeCanvasObjectMode === 'replace') {
|
|
605
551
|
ctx.restore();
|
|
606
552
|
return;
|
|
607
553
|
}
|
|
608
|
-
}
|
|
609
|
-
|
|
554
|
+
}
|
|
610
555
|
|
|
556
|
+
// Draw wider nodes by 1px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
|
|
611
557
|
var r = Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize + padAmount;
|
|
612
558
|
ctx.beginPath();
|
|
613
559
|
ctx.arc(node.x, node.y, r, 0, 2 * Math.PI, false);
|
|
614
560
|
ctx.fillStyle = getColor(node) || 'rgba(31, 120, 180, 0.92)';
|
|
615
561
|
ctx.fill();
|
|
616
|
-
|
|
617
562
|
if (state.nodeCanvasObject && nodeCanvasObjectMode === 'after') {
|
|
618
563
|
// Custom node after paint
|
|
619
564
|
state.nodeCanvasObject(node, state.ctx, state.globalScale);
|
|
@@ -621,27 +566,26 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
621
566
|
});
|
|
622
567
|
ctx.restore();
|
|
623
568
|
}
|
|
624
|
-
|
|
625
569
|
function paintLinks() {
|
|
626
|
-
var getVisibility =
|
|
627
|
-
var getColor =
|
|
628
|
-
var getWidth =
|
|
629
|
-
var getLineDash =
|
|
630
|
-
var getCurvature =
|
|
631
|
-
var getLinkCanvasObjectMode =
|
|
632
|
-
var ctx = state.ctx;
|
|
570
|
+
var getVisibility = accessorFn(state.linkVisibility);
|
|
571
|
+
var getColor = accessorFn(state.linkColor);
|
|
572
|
+
var getWidth = accessorFn(state.linkWidth);
|
|
573
|
+
var getLineDash = accessorFn(state.linkLineDash);
|
|
574
|
+
var getCurvature = accessorFn(state.linkCurvature);
|
|
575
|
+
var getLinkCanvasObjectMode = accessorFn(state.linkCanvasObjectMode);
|
|
576
|
+
var ctx = state.ctx;
|
|
633
577
|
|
|
578
|
+
// Draw wider lines by 2px on shadow canvas for more precise hovering (due to boundary anti-aliasing)
|
|
634
579
|
var padAmount = state.isShadow * 2;
|
|
635
580
|
var visibleLinks = state.graphData.links.filter(getVisibility);
|
|
636
581
|
visibleLinks.forEach(calcLinkControlPoints); // calculate curvature control points for all visible links
|
|
637
582
|
|
|
638
583
|
var beforeCustomLinks = [],
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
584
|
+
afterCustomLinks = [],
|
|
585
|
+
defaultPaintLinks = visibleLinks;
|
|
642
586
|
if (state.linkCanvasObject) {
|
|
643
587
|
var replaceCustomLinks = [],
|
|
644
|
-
|
|
588
|
+
otherCustomLinks = [];
|
|
645
589
|
visibleLinks.forEach(function (d) {
|
|
646
590
|
return ({
|
|
647
591
|
before: beforeCustomLinks,
|
|
@@ -651,34 +595,32 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
651
595
|
});
|
|
652
596
|
defaultPaintLinks = [].concat(_toConsumableArray(beforeCustomLinks), afterCustomLinks, otherCustomLinks);
|
|
653
597
|
beforeCustomLinks = beforeCustomLinks.concat(replaceCustomLinks);
|
|
654
|
-
}
|
|
655
|
-
|
|
598
|
+
}
|
|
656
599
|
|
|
600
|
+
// Custom link before paints
|
|
657
601
|
ctx.save();
|
|
658
602
|
beforeCustomLinks.forEach(function (link) {
|
|
659
603
|
return state.linkCanvasObject(link, ctx, state.globalScale);
|
|
660
604
|
});
|
|
661
|
-
ctx.restore();
|
|
605
|
+
ctx.restore();
|
|
662
606
|
|
|
663
|
-
|
|
607
|
+
// Bundle strokes per unique color/width/dash for performance optimization
|
|
608
|
+
var linksPerColor = indexBy(defaultPaintLinks, [getColor, getWidth, getLineDash]);
|
|
664
609
|
ctx.save();
|
|
665
610
|
Object.entries(linksPerColor).forEach(function (_ref) {
|
|
666
611
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
612
|
+
color = _ref2[0],
|
|
613
|
+
linksPerWidth = _ref2[1];
|
|
670
614
|
var lineColor = !color || color === 'undefined' ? 'rgba(0,0,0,0.15)' : color;
|
|
671
615
|
Object.entries(linksPerWidth).forEach(function (_ref3) {
|
|
672
616
|
var _ref4 = _slicedToArray(_ref3, 2),
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
617
|
+
width = _ref4[0],
|
|
618
|
+
linesPerLineDash = _ref4[1];
|
|
676
619
|
var lineWidth = (width || 1) / state.globalScale + padAmount;
|
|
677
620
|
Object.entries(linesPerLineDash).forEach(function (_ref5) {
|
|
678
621
|
var _ref6 = _slicedToArray(_ref5, 2);
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
622
|
+
_ref6[0];
|
|
623
|
+
var links = _ref6[1];
|
|
682
624
|
var lineDashSegments = getLineDash(links[0]);
|
|
683
625
|
ctx.beginPath();
|
|
684
626
|
links.forEach(function (link) {
|
|
@@ -688,7 +630,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
688
630
|
|
|
689
631
|
ctx.moveTo(start.x, start.y);
|
|
690
632
|
var controlPoints = link.__controlPoints;
|
|
691
|
-
|
|
692
633
|
if (!controlPoints) {
|
|
693
634
|
// Straight line
|
|
694
635
|
ctx.lineTo(end.x, end.y);
|
|
@@ -704,23 +645,24 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
704
645
|
});
|
|
705
646
|
});
|
|
706
647
|
});
|
|
707
|
-
ctx.restore();
|
|
648
|
+
ctx.restore();
|
|
708
649
|
|
|
650
|
+
// Custom link after paints
|
|
709
651
|
ctx.save();
|
|
710
652
|
afterCustomLinks.forEach(function (link) {
|
|
711
653
|
return state.linkCanvasObject(link, ctx, state.globalScale);
|
|
712
654
|
});
|
|
713
|
-
ctx.restore();
|
|
655
|
+
ctx.restore();
|
|
656
|
+
|
|
657
|
+
//
|
|
714
658
|
|
|
715
659
|
function calcLinkControlPoints(link) {
|
|
716
660
|
var curvature = getCurvature(link);
|
|
717
|
-
|
|
718
661
|
if (!curvature) {
|
|
719
662
|
// straight line
|
|
720
663
|
link.__controlPoints = null;
|
|
721
664
|
return;
|
|
722
665
|
}
|
|
723
|
-
|
|
724
666
|
var start = link.source;
|
|
725
667
|
var end = link.target;
|
|
726
668
|
if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link
|
|
@@ -729,7 +671,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
729
671
|
|
|
730
672
|
if (l > 0) {
|
|
731
673
|
var a = Math.atan2(end.y - start.y, end.x - start.x); // line angle
|
|
732
|
-
|
|
733
674
|
var d = l * curvature; // control point distance
|
|
734
675
|
|
|
735
676
|
var cp = {
|
|
@@ -741,20 +682,18 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
741
682
|
} else {
|
|
742
683
|
// Same point, draw a loop
|
|
743
684
|
var _d = curvature * 70;
|
|
744
|
-
|
|
745
685
|
link.__controlPoints = [end.x, end.y - _d, end.x + _d, end.y];
|
|
746
686
|
}
|
|
747
687
|
}
|
|
748
688
|
}
|
|
749
|
-
|
|
750
689
|
function paintArrows() {
|
|
751
690
|
var ARROW_WH_RATIO = 1.6;
|
|
752
691
|
var ARROW_VLEN_RATIO = 0.2;
|
|
753
|
-
var getLength =
|
|
754
|
-
var getRelPos =
|
|
755
|
-
var getVisibility =
|
|
756
|
-
var getColor =
|
|
757
|
-
var getNodeVal =
|
|
692
|
+
var getLength = accessorFn(state.linkDirectionalArrowLength);
|
|
693
|
+
var getRelPos = accessorFn(state.linkDirectionalArrowRelPos);
|
|
694
|
+
var getVisibility = accessorFn(state.linkVisibility);
|
|
695
|
+
var getColor = accessorFn(state.linkDirectionalArrowColor || state.linkColor);
|
|
696
|
+
var getNodeVal = accessorFn(state.nodeVal);
|
|
758
697
|
var ctx = state.ctx;
|
|
759
698
|
ctx.save();
|
|
760
699
|
state.graphData.links.filter(getVisibility).forEach(function (link) {
|
|
@@ -768,10 +707,10 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
768
707
|
var endR = Math.sqrt(Math.max(0, getNodeVal(end) || 1)) * state.nodeRelSize;
|
|
769
708
|
var arrowRelPos = Math.min(1, Math.max(0, getRelPos(link)));
|
|
770
709
|
var arrowColor = getColor(link) || 'rgba(0,0,0,0.28)';
|
|
771
|
-
var arrowHalfWidth = arrowLength / ARROW_WH_RATIO / 2;
|
|
710
|
+
var arrowHalfWidth = arrowLength / ARROW_WH_RATIO / 2;
|
|
772
711
|
|
|
712
|
+
// Construct bezier for curved lines
|
|
773
713
|
var bzLine = link.__controlPoints && _construct(bezierJs.Bezier, [start.x, start.y].concat(_toConsumableArray(link.__controlPoints), [end.x, end.y]));
|
|
774
|
-
|
|
775
714
|
var getCoordsAlongLine = bzLine ? function (t) {
|
|
776
715
|
return bzLine.get(t);
|
|
777
716
|
} // get position along bezier line
|
|
@@ -798,13 +737,12 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
798
737
|
});
|
|
799
738
|
ctx.restore();
|
|
800
739
|
}
|
|
801
|
-
|
|
802
740
|
function paintPhotons() {
|
|
803
|
-
var getNumPhotons =
|
|
804
|
-
var getSpeed =
|
|
805
|
-
var getDiameter =
|
|
806
|
-
var getVisibility =
|
|
807
|
-
var getColor =
|
|
741
|
+
var getNumPhotons = accessorFn(state.linkDirectionalParticles);
|
|
742
|
+
var getSpeed = accessorFn(state.linkDirectionalParticleSpeed);
|
|
743
|
+
var getDiameter = accessorFn(state.linkDirectionalParticleWidth);
|
|
744
|
+
var getVisibility = accessorFn(state.linkVisibility);
|
|
745
|
+
var getColor = accessorFn(state.linkDirectionalParticleColor || state.linkColor);
|
|
808
746
|
var ctx = state.ctx;
|
|
809
747
|
ctx.save();
|
|
810
748
|
state.graphData.links.filter(getVisibility).forEach(function (link) {
|
|
@@ -818,23 +756,20 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
818
756
|
var photons = link.__photons || [];
|
|
819
757
|
var photonR = Math.max(0, getDiameter(link) / 2) / Math.sqrt(state.globalScale);
|
|
820
758
|
var photonColor = getColor(link) || 'rgba(0,0,0,0.28)';
|
|
821
|
-
ctx.fillStyle = photonColor;
|
|
759
|
+
ctx.fillStyle = photonColor;
|
|
822
760
|
|
|
761
|
+
// Construct bezier for curved lines
|
|
823
762
|
var bzLine = link.__controlPoints ? _construct(bezierJs.Bezier, [start.x, start.y].concat(_toConsumableArray(link.__controlPoints), [end.x, end.y])) : null;
|
|
824
763
|
var cyclePhotonIdx = 0;
|
|
825
764
|
var needsCleanup = false; // whether some photons need to be removed from list
|
|
826
|
-
|
|
827
765
|
photons.forEach(function (photon) {
|
|
828
766
|
var singleHop = !!photon.__singleHop;
|
|
829
|
-
|
|
830
767
|
if (!photon.hasOwnProperty('__progressRatio')) {
|
|
831
768
|
photon.__progressRatio = singleHop ? 0 : cyclePhotonIdx / numCyclePhotons;
|
|
832
769
|
}
|
|
833
|
-
|
|
834
770
|
!singleHop && cyclePhotonIdx++; // increase regular photon index
|
|
835
771
|
|
|
836
772
|
photon.__progressRatio += particleSpeed;
|
|
837
|
-
|
|
838
773
|
if (photon.__progressRatio >= 1) {
|
|
839
774
|
if (!singleHop) {
|
|
840
775
|
photon.__progressRatio = photon.__progressRatio % 1;
|
|
@@ -843,7 +778,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
843
778
|
return;
|
|
844
779
|
}
|
|
845
780
|
}
|
|
846
|
-
|
|
847
781
|
var photonPosRatio = photon.__progressRatio;
|
|
848
782
|
var coords = bzLine ? bzLine.get(photonPosRatio) // get position along bezier line
|
|
849
783
|
: {
|
|
@@ -855,7 +789,6 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
855
789
|
ctx.arc(coords.x, coords.y, photonR, 0, 2 * Math.PI, false);
|
|
856
790
|
ctx.fill();
|
|
857
791
|
});
|
|
858
|
-
|
|
859
792
|
if (needsCleanup) {
|
|
860
793
|
// remove expired single hop photons
|
|
861
794
|
link.__photons = link.__photons.filter(function (photon) {
|
|
@@ -869,11 +802,9 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
869
802
|
emitParticle: function emitParticle(state, link) {
|
|
870
803
|
if (link) {
|
|
871
804
|
!link.__photons && (link.__photons = []);
|
|
872
|
-
|
|
873
805
|
link.__photons.push({
|
|
874
806
|
__singleHop: true
|
|
875
807
|
}); // add a single hop particle
|
|
876
|
-
|
|
877
808
|
}
|
|
878
809
|
|
|
879
810
|
return this;
|
|
@@ -891,31 +822,26 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
891
822
|
},
|
|
892
823
|
update: function update(state) {
|
|
893
824
|
state.engineRunning = false; // Pause simulation
|
|
894
|
-
|
|
895
825
|
state.onUpdate();
|
|
896
|
-
|
|
897
826
|
if (state.nodeAutoColorBy !== null) {
|
|
898
827
|
// Auto add color to uncolored nodes
|
|
899
|
-
autoColorObjects(state.graphData.nodes,
|
|
828
|
+
autoColorObjects(state.graphData.nodes, accessorFn(state.nodeAutoColorBy), state.nodeColor);
|
|
900
829
|
}
|
|
901
|
-
|
|
902
830
|
if (state.linkAutoColorBy !== null) {
|
|
903
831
|
// Auto add color to uncolored links
|
|
904
|
-
autoColorObjects(state.graphData.links,
|
|
905
|
-
}
|
|
906
|
-
|
|
832
|
+
autoColorObjects(state.graphData.links, accessorFn(state.linkAutoColorBy), state.linkColor);
|
|
833
|
+
}
|
|
907
834
|
|
|
835
|
+
// parse links
|
|
908
836
|
state.graphData.links.forEach(function (link) {
|
|
909
837
|
link.source = link[state.linkSource];
|
|
910
838
|
link.target = link[state.linkTarget];
|
|
911
839
|
});
|
|
912
|
-
|
|
913
840
|
if (!state.isShadow) {
|
|
914
841
|
// Add photon particles
|
|
915
|
-
var linkParticlesAccessor =
|
|
842
|
+
var linkParticlesAccessor = accessorFn(state.linkDirectionalParticles);
|
|
916
843
|
state.graphData.links.forEach(function (link) {
|
|
917
844
|
var numPhotons = Math.round(Math.abs(linkParticlesAccessor(link)));
|
|
918
|
-
|
|
919
845
|
if (numPhotons) {
|
|
920
846
|
link.__photons = _toConsumableArray(Array(numPhotons)).map(function () {
|
|
921
847
|
return {};
|
|
@@ -924,21 +850,21 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
924
850
|
delete link.__photons;
|
|
925
851
|
}
|
|
926
852
|
});
|
|
927
|
-
}
|
|
928
|
-
|
|
853
|
+
}
|
|
929
854
|
|
|
855
|
+
// Feed data to force-directed layout
|
|
930
856
|
state.forceLayout.stop().alpha(1) // re-heat the simulation
|
|
931
|
-
.nodes(state.graphData.nodes);
|
|
857
|
+
.nodes(state.graphData.nodes);
|
|
932
858
|
|
|
859
|
+
// add links (if link force is still active)
|
|
933
860
|
var linkForce = state.forceLayout.force('link');
|
|
934
|
-
|
|
935
861
|
if (linkForce) {
|
|
936
862
|
linkForce.id(function (d) {
|
|
937
863
|
return d[state.nodeId];
|
|
938
864
|
}).links(state.graphData.links);
|
|
939
|
-
}
|
|
940
|
-
|
|
865
|
+
}
|
|
941
866
|
|
|
867
|
+
// setup dag force constraints
|
|
942
868
|
var nodeDepths = state.dagMode && getDagDepths(state.graphData, function (node) {
|
|
943
869
|
return node[state.nodeId];
|
|
944
870
|
}, {
|
|
@@ -946,36 +872,34 @@ var CanvasForceGraph = Kapsule__default["default"]({
|
|
|
946
872
|
onLoopError: state.onDagError || undefined
|
|
947
873
|
});
|
|
948
874
|
var maxDepth = Math.max.apply(Math, _toConsumableArray(Object.values(nodeDepths || [])));
|
|
949
|
-
var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1);
|
|
875
|
+
var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1);
|
|
950
876
|
|
|
877
|
+
// Fix nodes to x,y for dag mode
|
|
951
878
|
if (state.dagMode) {
|
|
952
879
|
var getFFn = function getFFn(fix, invert) {
|
|
953
880
|
return function (node) {
|
|
954
881
|
return !fix ? undefined : (nodeDepths[node[state.nodeId]] - maxDepth / 2) * dagLevelDistance * (invert ? -1 : 1);
|
|
955
882
|
};
|
|
956
883
|
};
|
|
957
|
-
|
|
958
884
|
var fxFn = getFFn(['lr', 'rl'].indexOf(state.dagMode) !== -1, state.dagMode === 'rl');
|
|
959
885
|
var fyFn = getFFn(['td', 'bu'].indexOf(state.dagMode) !== -1, state.dagMode === 'bu');
|
|
960
886
|
state.graphData.nodes.filter(state.dagNodeFilter).forEach(function (node) {
|
|
961
887
|
node.fx = fxFn(node);
|
|
962
888
|
node.fy = fyFn(node);
|
|
963
889
|
});
|
|
964
|
-
}
|
|
965
|
-
|
|
890
|
+
}
|
|
966
891
|
|
|
892
|
+
// Use radial force for radial dags
|
|
967
893
|
state.forceLayout.force('dagRadial', ['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? d3Force3d.forceRadial(function (node) {
|
|
968
894
|
var nodeDepth = nodeDepths[node[state.nodeId]] || -1;
|
|
969
895
|
return (state.dagMode === 'radialin' ? maxDepth - nodeDepth : nodeDepth) * dagLevelDistance;
|
|
970
896
|
}).strength(function (node) {
|
|
971
897
|
return state.dagNodeFilter(node) ? 1 : 0;
|
|
972
898
|
}) : null);
|
|
973
|
-
|
|
974
899
|
for (var i = 0; i < state.warmupTicks && !(state.d3AlphaMin > 0 && state.forceLayout.alpha() < state.d3AlphaMin); i++) {
|
|
975
900
|
state.forceLayout.tick();
|
|
976
901
|
} // Initial ticks before starting to render
|
|
977
902
|
|
|
978
|
-
|
|
979
903
|
this.resetCountdown();
|
|
980
904
|
state.onFinishUpdate();
|
|
981
905
|
}
|
|
@@ -1004,12 +928,10 @@ function linkKapsule (kapsulePropNames, kapsuleType) {
|
|
|
1004
928
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
1005
929
|
args[_key - 1] = arguments[_key];
|
|
1006
930
|
}
|
|
1007
|
-
|
|
1008
931
|
var returnVals = [];
|
|
1009
932
|
propNames.forEach(function (propName) {
|
|
1010
933
|
var kapsuleInstance = state[propName];
|
|
1011
934
|
var returnVal = kapsuleInstance[method].apply(kapsuleInstance, args);
|
|
1012
|
-
|
|
1013
935
|
if (returnVal !== kapsuleInstance) {
|
|
1014
936
|
returnVals.push(returnVal);
|
|
1015
937
|
}
|
|
@@ -1021,9 +943,9 @@ function linkKapsule (kapsulePropNames, kapsuleType) {
|
|
|
1021
943
|
}
|
|
1022
944
|
|
|
1023
945
|
var HOVER_CANVAS_THROTTLE_DELAY = 800; // ms to throttle shadow canvas updates for perf improvement
|
|
946
|
+
var ZOOM2NODES_FACTOR = 4;
|
|
1024
947
|
|
|
1025
|
-
|
|
1026
|
-
|
|
948
|
+
// Expose config from forceGraph
|
|
1027
949
|
var bindFG = linkKapsule('forceGraph', CanvasForceGraph);
|
|
1028
950
|
var bindBoth = linkKapsule(['forceGraph', 'shadowGraph'], CanvasForceGraph);
|
|
1029
951
|
var linkedProps = Object.assign.apply(Object, _toConsumableArray(['nodeColor', 'nodeAutoColorBy', 'nodeCanvasObject', 'nodeCanvasObjectMode', 'linkColor', 'linkAutoColorBy', 'linkLineDash', 'linkWidth', 'linkCanvasObject', 'linkCanvasObjectMode', 'linkDirectionalArrowLength', 'linkDirectionalArrowColor', 'linkDirectionalArrowRelPos', 'linkDirectionalParticles', 'linkDirectionalParticleSpeed', 'linkDirectionalParticleWidth', 'linkDirectionalParticleColor', 'dagMode', 'dagLevelDistance', 'dagNodeFilter', 'onDagError', 'd3AlphaMin', 'd3AlphaDecay', 'd3VelocityDecay', 'warmupTicks', 'cooldownTicks', 'cooldownTime', 'onEngineTick', 'onEngineStop'].map(function (p) {
|
|
@@ -1034,56 +956,54 @@ var linkedProps = Object.assign.apply(Object, _toConsumableArray(['nodeColor', '
|
|
|
1034
956
|
var linkedMethods = Object.assign.apply(Object, _toConsumableArray(['d3Force', 'd3ReheatSimulation', 'emitParticle'].map(function (p) {
|
|
1035
957
|
return _defineProperty({}, p, bindFG.linkMethod(p));
|
|
1036
958
|
})));
|
|
1037
|
-
|
|
1038
959
|
function adjustCanvasSize(state) {
|
|
1039
960
|
if (state.canvas) {
|
|
1040
961
|
var curWidth = state.canvas.width;
|
|
1041
962
|
var curHeight = state.canvas.height;
|
|
1042
|
-
|
|
1043
963
|
if (curWidth === 300 && curHeight === 150) {
|
|
1044
964
|
// Default canvas dimensions
|
|
1045
965
|
curWidth = curHeight = 0;
|
|
1046
966
|
}
|
|
1047
|
-
|
|
1048
967
|
var pxScale = window.devicePixelRatio; // 2 on retina displays
|
|
1049
|
-
|
|
1050
968
|
curWidth /= pxScale;
|
|
1051
|
-
curHeight /= pxScale;
|
|
969
|
+
curHeight /= pxScale;
|
|
1052
970
|
|
|
971
|
+
// Resize canvases
|
|
1053
972
|
[state.canvas, state.shadowCanvas].forEach(function (canvas) {
|
|
1054
973
|
// Element size
|
|
1055
974
|
canvas.style.width = "".concat(state.width, "px");
|
|
1056
|
-
canvas.style.height = "".concat(state.height, "px");
|
|
975
|
+
canvas.style.height = "".concat(state.height, "px");
|
|
1057
976
|
|
|
977
|
+
// Memory size (scaled to avoid blurriness)
|
|
1058
978
|
canvas.width = state.width * pxScale;
|
|
1059
|
-
canvas.height = state.height * pxScale;
|
|
979
|
+
canvas.height = state.height * pxScale;
|
|
1060
980
|
|
|
981
|
+
// Normalize coordinate system to use css pixels (on init only)
|
|
1061
982
|
if (!curWidth && !curHeight) {
|
|
1062
983
|
canvas.getContext('2d').scale(pxScale, pxScale);
|
|
1063
984
|
}
|
|
1064
|
-
});
|
|
985
|
+
});
|
|
1065
986
|
|
|
987
|
+
// Relative center panning based on 0,0
|
|
1066
988
|
var k = d3Zoom.zoomTransform(state.canvas).k;
|
|
1067
989
|
state.zoom.translateBy(state.zoom.__baseElem, (state.width - curWidth) / 2 / k, (state.height - curHeight) / 2 / k);
|
|
1068
990
|
state.needsRedraw = true;
|
|
1069
991
|
}
|
|
1070
992
|
}
|
|
1071
|
-
|
|
1072
993
|
function resetTransform(ctx) {
|
|
1073
994
|
var pxRatio = window.devicePixelRatio;
|
|
1074
995
|
ctx.setTransform(pxRatio, 0, 0, pxRatio, 0, 0);
|
|
1075
996
|
}
|
|
1076
|
-
|
|
1077
997
|
function clearCanvas(ctx, width, height) {
|
|
1078
998
|
ctx.save();
|
|
1079
999
|
resetTransform(ctx); // reset transform
|
|
1080
|
-
|
|
1081
1000
|
ctx.clearRect(0, 0, width, height);
|
|
1082
1001
|
ctx.restore(); //restore transforms
|
|
1083
|
-
}
|
|
1002
|
+
}
|
|
1084
1003
|
|
|
1004
|
+
//
|
|
1085
1005
|
|
|
1086
|
-
var forceGraph =
|
|
1006
|
+
var forceGraph = Kapsule({
|
|
1087
1007
|
props: _objectSpread2({
|
|
1088
1008
|
width: {
|
|
1089
1009
|
"default": window.innerWidth,
|
|
@@ -1114,10 +1034,9 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1114
1034
|
}].forEach(hexIndex);
|
|
1115
1035
|
state.forceGraph.graphData(d);
|
|
1116
1036
|
state.shadowGraph.graphData(d);
|
|
1117
|
-
|
|
1118
1037
|
function hexIndex(_ref4) {
|
|
1119
1038
|
var type = _ref4.type,
|
|
1120
|
-
|
|
1039
|
+
objs = _ref4.objs;
|
|
1121
1040
|
objs.filter(function (d) {
|
|
1122
1041
|
if (!d.hasOwnProperty('__indexColor')) return true;
|
|
1123
1042
|
var cur = state.colorTracker.lookup(d.__indexColor);
|
|
@@ -1277,27 +1196,27 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1277
1196
|
},
|
|
1278
1197
|
centerAt: function centerAt(state, x, y, transitionDuration) {
|
|
1279
1198
|
if (!state.canvas) return null; // no canvas yet
|
|
1280
|
-
// setter
|
|
1281
1199
|
|
|
1200
|
+
// setter
|
|
1282
1201
|
if (x !== undefined || y !== undefined) {
|
|
1283
1202
|
var finalPos = Object.assign({}, x !== undefined ? {
|
|
1284
1203
|
x: x
|
|
1285
1204
|
} : {}, y !== undefined ? {
|
|
1286
1205
|
y: y
|
|
1287
1206
|
} : {});
|
|
1288
|
-
|
|
1289
1207
|
if (!transitionDuration) {
|
|
1290
1208
|
// no animation
|
|
1291
1209
|
setCenter(finalPos);
|
|
1292
1210
|
} else {
|
|
1293
|
-
new
|
|
1211
|
+
new TWEEN.Tween(getCenter()).to(finalPos, transitionDuration).easing(TWEEN.Easing.Quadratic.Out).onUpdate(setCenter).start();
|
|
1294
1212
|
}
|
|
1295
|
-
|
|
1296
1213
|
return this;
|
|
1297
|
-
}
|
|
1214
|
+
}
|
|
1298
1215
|
|
|
1216
|
+
// getter
|
|
1217
|
+
return getCenter();
|
|
1299
1218
|
|
|
1300
|
-
|
|
1219
|
+
//
|
|
1301
1220
|
|
|
1302
1221
|
function getCenter() {
|
|
1303
1222
|
var t = d3Zoom.zoomTransform(state.canvas);
|
|
@@ -1306,43 +1225,42 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1306
1225
|
y: (state.height / 2 - t.y) / t.k
|
|
1307
1226
|
};
|
|
1308
1227
|
}
|
|
1309
|
-
|
|
1310
1228
|
function setCenter(_ref5) {
|
|
1311
1229
|
var x = _ref5.x,
|
|
1312
|
-
|
|
1230
|
+
y = _ref5.y;
|
|
1313
1231
|
state.zoom.translateTo(state.zoom.__baseElem, x === undefined ? getCenter().x : x, y === undefined ? getCenter().y : y);
|
|
1314
1232
|
state.needsRedraw = true;
|
|
1315
1233
|
}
|
|
1316
1234
|
},
|
|
1317
1235
|
zoom: function zoom(state, k, transitionDuration) {
|
|
1318
1236
|
if (!state.canvas) return null; // no canvas yet
|
|
1319
|
-
// setter
|
|
1320
1237
|
|
|
1238
|
+
// setter
|
|
1321
1239
|
if (k !== undefined) {
|
|
1322
1240
|
if (!transitionDuration) {
|
|
1323
1241
|
// no animation
|
|
1324
1242
|
setZoom(k);
|
|
1325
1243
|
} else {
|
|
1326
|
-
new
|
|
1244
|
+
new TWEEN.Tween({
|
|
1327
1245
|
k: getZoom()
|
|
1328
1246
|
}).to({
|
|
1329
1247
|
k: k
|
|
1330
|
-
}, transitionDuration).easing(
|
|
1248
|
+
}, transitionDuration).easing(TWEEN.Easing.Quadratic.Out).onUpdate(function (_ref6) {
|
|
1331
1249
|
var k = _ref6.k;
|
|
1332
1250
|
return setZoom(k);
|
|
1333
1251
|
}).start();
|
|
1334
1252
|
}
|
|
1335
|
-
|
|
1336
1253
|
return this;
|
|
1337
|
-
}
|
|
1254
|
+
}
|
|
1338
1255
|
|
|
1256
|
+
// getter
|
|
1257
|
+
return getZoom();
|
|
1339
1258
|
|
|
1340
|
-
|
|
1259
|
+
//
|
|
1341
1260
|
|
|
1342
1261
|
function getZoom() {
|
|
1343
1262
|
return d3Zoom.zoomTransform(state.canvas).k;
|
|
1344
1263
|
}
|
|
1345
|
-
|
|
1346
1264
|
function setZoom(k) {
|
|
1347
1265
|
state.zoom.scaleTo(state.zoom.__baseElem, k);
|
|
1348
1266
|
state.needsRedraw = true;
|
|
@@ -1351,13 +1269,10 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1351
1269
|
zoomToFit: function zoomToFit(state) {
|
|
1352
1270
|
var transitionDuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
1353
1271
|
var padding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;
|
|
1354
|
-
|
|
1355
1272
|
for (var _len = arguments.length, bboxArgs = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
|
|
1356
1273
|
bboxArgs[_key - 3] = arguments[_key];
|
|
1357
1274
|
}
|
|
1358
|
-
|
|
1359
1275
|
var bbox = this.getGraphBbox.apply(this, bboxArgs);
|
|
1360
|
-
|
|
1361
1276
|
if (bbox) {
|
|
1362
1277
|
var center = {
|
|
1363
1278
|
x: (bbox.x[0] + bbox.x[1]) / 2,
|
|
@@ -1367,19 +1282,16 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1367
1282
|
this.centerAt(center.x, center.y, transitionDuration);
|
|
1368
1283
|
this.zoom(zoomK, transitionDuration);
|
|
1369
1284
|
}
|
|
1370
|
-
|
|
1371
1285
|
return this;
|
|
1372
1286
|
},
|
|
1373
1287
|
getGraphBbox: function getGraphBbox(state) {
|
|
1374
1288
|
var nodeFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
|
|
1375
1289
|
return true;
|
|
1376
1290
|
};
|
|
1377
|
-
var getVal =
|
|
1378
|
-
|
|
1291
|
+
var getVal = accessorFn(state.nodeVal);
|
|
1379
1292
|
var getR = function getR(node) {
|
|
1380
1293
|
return Math.sqrt(Math.max(0, getVal(node) || 1)) * state.nodeRelSize;
|
|
1381
1294
|
};
|
|
1382
|
-
|
|
1383
1295
|
var nodesPos = state.graphData.nodes.filter(nodeFilter).map(function (node) {
|
|
1384
1296
|
return {
|
|
1385
1297
|
x: node.x,
|
|
@@ -1405,14 +1317,12 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1405
1317
|
cancelAnimationFrame(state.animationFrameRequestId);
|
|
1406
1318
|
state.animationFrameRequestId = null;
|
|
1407
1319
|
}
|
|
1408
|
-
|
|
1409
1320
|
return this;
|
|
1410
1321
|
},
|
|
1411
1322
|
resumeAnimation: function resumeAnimation(state) {
|
|
1412
1323
|
if (!state.animationFrameRequestId) {
|
|
1413
1324
|
this._animationCycle();
|
|
1414
1325
|
}
|
|
1415
|
-
|
|
1416
1326
|
return this;
|
|
1417
1327
|
},
|
|
1418
1328
|
_destructor: function _destructor() {
|
|
@@ -1429,16 +1339,16 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1429
1339
|
zoom: d3Zoom.zoom(),
|
|
1430
1340
|
forceGraph: new CanvasForceGraph(),
|
|
1431
1341
|
shadowGraph: new CanvasForceGraph().cooldownTicks(0).nodeColor('__indexColor').linkColor('__indexColor').isShadow(true),
|
|
1432
|
-
colorTracker: new
|
|
1433
|
-
|
|
1342
|
+
colorTracker: new ColorTracker() // indexed objects for rgb lookup
|
|
1434
1343
|
};
|
|
1435
1344
|
},
|
|
1345
|
+
|
|
1436
1346
|
init: function init(domNode, state) {
|
|
1437
1347
|
var _this = this;
|
|
1438
|
-
|
|
1439
1348
|
// Wipe DOM
|
|
1440
|
-
domNode.innerHTML = '';
|
|
1349
|
+
domNode.innerHTML = '';
|
|
1441
1350
|
|
|
1351
|
+
// Container anchor for canvas and tooltip
|
|
1442
1352
|
var container = document.createElement('div');
|
|
1443
1353
|
container.classList.add('force-graph-container');
|
|
1444
1354
|
container.style.position = 'relative';
|
|
@@ -1446,7 +1356,9 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1446
1356
|
state.canvas = document.createElement('canvas');
|
|
1447
1357
|
if (state.backgroundColor) state.canvas.style.background = state.backgroundColor;
|
|
1448
1358
|
container.appendChild(state.canvas);
|
|
1449
|
-
state.shadowCanvas = document.createElement('canvas');
|
|
1359
|
+
state.shadowCanvas = document.createElement('canvas');
|
|
1360
|
+
|
|
1361
|
+
// Show shadow canvas
|
|
1450
1362
|
//state.shadowCanvas.style.position = 'absolute';
|
|
1451
1363
|
//state.shadowCanvas.style.top = '0';
|
|
1452
1364
|
//state.shadowCanvas.style.left = '0';
|
|
@@ -1458,22 +1370,20 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1458
1370
|
x: -1e12,
|
|
1459
1371
|
y: -1e12
|
|
1460
1372
|
};
|
|
1461
|
-
|
|
1462
1373
|
var getObjUnderPointer = function getObjUnderPointer() {
|
|
1463
1374
|
var obj = null;
|
|
1464
1375
|
var pxScale = window.devicePixelRatio;
|
|
1465
|
-
var px = pointerPos.x > 0 && pointerPos.y > 0 ? shadowCtx.getImageData(pointerPos.x * pxScale, pointerPos.y * pxScale, 1, 1) : null;
|
|
1466
|
-
|
|
1376
|
+
var px = pointerPos.x > 0 && pointerPos.y > 0 ? shadowCtx.getImageData(pointerPos.x * pxScale, pointerPos.y * pxScale, 1, 1) : null;
|
|
1377
|
+
// Lookup object per pixel color
|
|
1467
1378
|
px && (obj = state.colorTracker.lookup(px.data));
|
|
1468
1379
|
return obj;
|
|
1469
|
-
};
|
|
1470
|
-
|
|
1380
|
+
};
|
|
1471
1381
|
|
|
1382
|
+
// Setup node drag interaction
|
|
1472
1383
|
d3Selection.select(state.canvas).call(d3Drag.drag().subject(function () {
|
|
1473
1384
|
if (!state.enableNodeDrag) {
|
|
1474
1385
|
return null;
|
|
1475
1386
|
}
|
|
1476
|
-
|
|
1477
1387
|
var obj = getObjUnderPointer();
|
|
1478
1388
|
return obj && obj.type === 'Node' ? obj.d : null; // Only drag nodes
|
|
1479
1389
|
}).on('start', function (ev) {
|
|
@@ -1483,14 +1393,15 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1483
1393
|
y: obj.y,
|
|
1484
1394
|
fx: obj.fx,
|
|
1485
1395
|
fy: obj.fy
|
|
1486
|
-
};
|
|
1396
|
+
};
|
|
1487
1397
|
|
|
1398
|
+
// keep engine running at low intensity throughout drag
|
|
1488
1399
|
if (!ev.active) {
|
|
1489
1400
|
obj.fx = obj.x;
|
|
1490
1401
|
obj.fy = obj.y; // Fix points
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1402
|
+
}
|
|
1493
1403
|
|
|
1404
|
+
// drag cursor
|
|
1494
1405
|
state.canvas.classList.add('grabbable');
|
|
1495
1406
|
}).on('drag', function (ev) {
|
|
1496
1407
|
var obj = ev.subject;
|
|
@@ -1500,12 +1411,14 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1500
1411
|
var translate = {
|
|
1501
1412
|
x: initPos.x + (dragPos.x - initPos.x) / k - obj.x,
|
|
1502
1413
|
y: initPos.y + (dragPos.y - initPos.y) / k - obj.y
|
|
1503
|
-
};
|
|
1414
|
+
};
|
|
1504
1415
|
|
|
1416
|
+
// Move fx/fy (and x/y) of nodes based on the scaled drag distance since the drag start
|
|
1505
1417
|
['x', 'y'].forEach(function (c) {
|
|
1506
1418
|
return obj["f".concat(c)] = obj[c] = initPos[c] + (dragPos[c] - initPos[c]) / k;
|
|
1507
|
-
});
|
|
1419
|
+
});
|
|
1508
1420
|
|
|
1421
|
+
// prevent freeze while dragging
|
|
1509
1422
|
state.forceGraph.d3AlphaTarget(0.3) // keep engine running at low intensity throughout drag
|
|
1510
1423
|
.resetCountdown(); // prevent freeze while dragging
|
|
1511
1424
|
|
|
@@ -1519,39 +1432,35 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1519
1432
|
x: obj.x - initPos.x,
|
|
1520
1433
|
y: obj.y - initPos.y
|
|
1521
1434
|
};
|
|
1522
|
-
|
|
1523
1435
|
if (initPos.fx === undefined) {
|
|
1524
1436
|
obj.fx = undefined;
|
|
1525
1437
|
}
|
|
1526
|
-
|
|
1527
1438
|
if (initPos.fy === undefined) {
|
|
1528
1439
|
obj.fy = undefined;
|
|
1529
1440
|
}
|
|
1530
|
-
|
|
1531
1441
|
delete obj.__initialDragPos;
|
|
1532
|
-
|
|
1533
1442
|
if (state.forceGraph.d3AlphaTarget()) {
|
|
1534
1443
|
state.forceGraph.d3AlphaTarget(0) // release engine low intensity
|
|
1535
1444
|
.resetCountdown(); // let the engine readjust after releasing fixed nodes
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1445
|
+
}
|
|
1538
1446
|
|
|
1447
|
+
// drag cursor
|
|
1539
1448
|
state.canvas.classList.remove('grabbable');
|
|
1540
1449
|
state.isPointerDragging = false;
|
|
1541
|
-
|
|
1542
1450
|
if (obj.__dragged) {
|
|
1543
1451
|
delete obj.__dragged;
|
|
1544
1452
|
state.onNodeDragEnd(obj, translate);
|
|
1545
1453
|
}
|
|
1546
|
-
}));
|
|
1454
|
+
}));
|
|
1547
1455
|
|
|
1456
|
+
// Setup zoom / pan interaction
|
|
1548
1457
|
state.zoom(state.zoom.__baseElem = d3Selection.select(state.canvas)); // Attach controlling elem for easy access
|
|
1549
1458
|
|
|
1550
1459
|
state.zoom.__baseElem.on('dblclick.zoom', null); // Disable double-click to zoom
|
|
1551
1460
|
|
|
1552
|
-
|
|
1553
1461
|
state.zoom.filter(function (ev) {
|
|
1554
|
-
return (
|
|
1462
|
+
return (
|
|
1463
|
+
// disable zoom interaction
|
|
1555
1464
|
!ev.button && state.enableZoomPanInteraction && (state.enableZoomInteraction || ev.type !== 'wheel') && (state.enablePanInteraction || ev.type === 'wheel')
|
|
1556
1465
|
);
|
|
1557
1466
|
}).on('zoom', function (ev) {
|
|
@@ -1562,7 +1471,6 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1562
1471
|
c.scale(t.k, t.k);
|
|
1563
1472
|
});
|
|
1564
1473
|
state.onZoom && state.onZoom(_objectSpread2(_objectSpread2({}, t), _this.centerAt())); // report x,y coordinates relative to canvas center
|
|
1565
|
-
|
|
1566
1474
|
state.needsRedraw = true;
|
|
1567
1475
|
}).on('end', function (ev) {
|
|
1568
1476
|
return state.onZoomEnd && state.onZoomEnd(_objectSpread2(_objectSpread2({}, ev.transform), _this.centerAt()));
|
|
@@ -1576,39 +1484,49 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1576
1484
|
state.zoom.scaleTo(state.zoom.__baseElem, state.lastSetZoom = ZOOM2NODES_FACTOR / Math.cbrt(state.graphData.nodes.length));
|
|
1577
1485
|
state.needsRedraw = true;
|
|
1578
1486
|
}
|
|
1579
|
-
});
|
|
1487
|
+
});
|
|
1580
1488
|
|
|
1489
|
+
// Setup tooltip
|
|
1581
1490
|
var toolTipElem = document.createElement('div');
|
|
1582
1491
|
toolTipElem.classList.add('graph-tooltip');
|
|
1583
|
-
container.appendChild(toolTipElem);
|
|
1492
|
+
container.appendChild(toolTipElem);
|
|
1584
1493
|
|
|
1494
|
+
// Capture pointer coords on move or touchstart
|
|
1585
1495
|
['pointermove', 'pointerdown'].forEach(function (evType) {
|
|
1586
1496
|
return container.addEventListener(evType, function (ev) {
|
|
1587
1497
|
if (evType === 'pointerdown') {
|
|
1588
1498
|
state.isPointerPressed = true; // track click state
|
|
1589
|
-
|
|
1590
1499
|
state.pointerDownEvent = ev;
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1500
|
+
}
|
|
1593
1501
|
|
|
1502
|
+
// detect pointer drag on canvas pan
|
|
1594
1503
|
!state.isPointerDragging && ev.type === 'pointermove' && state.onBackgroundClick // only bother detecting drags this way if background clicks are enabled (so they don't trigger accidentally on canvas panning)
|
|
1595
1504
|
&& (ev.pressure > 0 || state.isPointerPressed) // ev.pressure always 0 on Safari, so we use the isPointerPressed tracker
|
|
1596
1505
|
&& (ev.pointerType !== 'touch' || ev.movementX === undefined || [ev.movementX, ev.movementY].some(function (m) {
|
|
1597
1506
|
return Math.abs(m) > 1;
|
|
1598
1507
|
})) // relax drag trigger sensitivity on touch events
|
|
1599
|
-
&& (state.isPointerDragging = true);
|
|
1508
|
+
&& (state.isPointerDragging = true);
|
|
1600
1509
|
|
|
1510
|
+
// update the pointer pos
|
|
1601
1511
|
var offset = getOffset(container);
|
|
1602
1512
|
pointerPos.x = ev.pageX - offset.left;
|
|
1603
|
-
pointerPos.y = ev.pageY - offset.top;
|
|
1513
|
+
pointerPos.y = ev.pageY - offset.top;
|
|
1604
1514
|
|
|
1515
|
+
// Move tooltip
|
|
1605
1516
|
toolTipElem.style.top = "".concat(pointerPos.y, "px");
|
|
1606
|
-
toolTipElem.style.left = "".concat(pointerPos.x, "px");
|
|
1517
|
+
toolTipElem.style.left = "".concat(pointerPos.x, "px");
|
|
1518
|
+
|
|
1519
|
+
// adjust horizontal position to not exceed canvas boundaries
|
|
1520
|
+
toolTipElem.style.transform = "translate(-".concat(pointerPos.x / state.width * 100, "%, ").concat(
|
|
1521
|
+
// flip to above if near bottom
|
|
1522
|
+
state.height - pointerPos.y < 100 ? 'calc(-100% - 8px)' : '21px', ")");
|
|
1523
|
+
|
|
1524
|
+
//
|
|
1607
1525
|
|
|
1608
1526
|
function getOffset(el) {
|
|
1609
1527
|
var rect = el.getBoundingClientRect(),
|
|
1610
|
-
|
|
1611
|
-
|
|
1528
|
+
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
|
|
1529
|
+
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
1612
1530
|
return {
|
|
1613
1531
|
top: rect.top + scrollTop,
|
|
1614
1532
|
left: rect.left + scrollLeft
|
|
@@ -1617,11 +1535,11 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1617
1535
|
}, {
|
|
1618
1536
|
passive: true
|
|
1619
1537
|
});
|
|
1620
|
-
});
|
|
1538
|
+
});
|
|
1621
1539
|
|
|
1540
|
+
// Handle click/touch events on nodes/links
|
|
1622
1541
|
container.addEventListener('pointerup', function (ev) {
|
|
1623
1542
|
state.isPointerPressed = false;
|
|
1624
|
-
|
|
1625
1543
|
if (state.isPointerDragging) {
|
|
1626
1544
|
state.isPointerDragging = false;
|
|
1627
1545
|
return; // don't trigger click events after pointer drag (pan / node drag functionality)
|
|
@@ -1639,7 +1557,6 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1639
1557
|
state.onBackgroundClick && state.onBackgroundClick.apply(state, cbEvents);
|
|
1640
1558
|
}
|
|
1641
1559
|
}
|
|
1642
|
-
|
|
1643
1560
|
if (ev.button === 2) {
|
|
1644
1561
|
// mouse right-click
|
|
1645
1562
|
if (state.hoverObj) {
|
|
@@ -1655,77 +1572,74 @@ var forceGraph = Kapsule__default["default"]({
|
|
|
1655
1572
|
});
|
|
1656
1573
|
container.addEventListener('contextmenu', function (ev) {
|
|
1657
1574
|
if (!state.onBackgroundRightClick && !state.onNodeRightClick && !state.onLinkRightClick) return true; // default contextmenu behavior
|
|
1658
|
-
|
|
1659
1575
|
ev.preventDefault();
|
|
1660
1576
|
return false;
|
|
1661
1577
|
});
|
|
1662
1578
|
state.forceGraph(ctx);
|
|
1663
|
-
state.shadowGraph(shadowCtx);
|
|
1579
|
+
state.shadowGraph(shadowCtx);
|
|
1580
|
+
|
|
1581
|
+
//
|
|
1664
1582
|
|
|
1665
|
-
var refreshShadowCanvas =
|
|
1583
|
+
var refreshShadowCanvas = throttle(function () {
|
|
1666
1584
|
// wipe canvas
|
|
1667
|
-
clearCanvas(shadowCtx, state.width, state.height);
|
|
1585
|
+
clearCanvas(shadowCtx, state.width, state.height);
|
|
1668
1586
|
|
|
1587
|
+
// Adjust link hover area
|
|
1669
1588
|
state.shadowGraph.linkWidth(function (l) {
|
|
1670
|
-
return
|
|
1671
|
-
});
|
|
1589
|
+
return accessorFn(state.linkWidth)(l) + state.linkHoverPrecision;
|
|
1590
|
+
});
|
|
1672
1591
|
|
|
1592
|
+
// redraw
|
|
1673
1593
|
var t = d3Zoom.zoomTransform(state.canvas);
|
|
1674
1594
|
state.shadowGraph.globalScale(t.k).tickFrame();
|
|
1675
1595
|
}, HOVER_CANVAS_THROTTLE_DELAY);
|
|
1676
1596
|
state.flushShadowCanvas = refreshShadowCanvas.flush; // hook to immediately invoke shadow canvas paint
|
|
1677
|
-
// Kick-off renderer
|
|
1678
1597
|
|
|
1598
|
+
// Kick-off renderer
|
|
1679
1599
|
(this._animationCycle = function animate() {
|
|
1680
1600
|
// IIFE
|
|
1681
1601
|
var doRedraw = !state.autoPauseRedraw || !!state.needsRedraw || state.forceGraph.isEngineRunning() || state.graphData.links.some(function (d) {
|
|
1682
1602
|
return d.__photons && d.__photons.length;
|
|
1683
1603
|
});
|
|
1684
1604
|
state.needsRedraw = false;
|
|
1685
|
-
|
|
1686
1605
|
if (state.enablePointerInteraction) {
|
|
1687
1606
|
// Update tooltip and trigger onHover events
|
|
1688
1607
|
var obj = !state.isPointerDragging ? getObjUnderPointer() : null; // don't hover during drag
|
|
1689
|
-
|
|
1690
1608
|
if (obj !== state.hoverObj) {
|
|
1691
1609
|
var prevObj = state.hoverObj;
|
|
1692
1610
|
var prevObjType = prevObj ? prevObj.type : null;
|
|
1693
1611
|
var objType = obj ? obj.type : null;
|
|
1694
|
-
|
|
1695
1612
|
if (prevObjType && prevObjType !== objType) {
|
|
1696
1613
|
// Hover out
|
|
1697
1614
|
var fn = state["on".concat(prevObjType, "Hover")];
|
|
1698
1615
|
fn && fn(null, prevObj.d);
|
|
1699
1616
|
}
|
|
1700
|
-
|
|
1701
1617
|
if (objType) {
|
|
1702
1618
|
// Hover in
|
|
1703
1619
|
var _fn2 = state["on".concat(objType, "Hover")];
|
|
1704
1620
|
_fn2 && _fn2(obj.d, prevObjType === objType ? prevObj.d : null);
|
|
1705
1621
|
}
|
|
1706
|
-
|
|
1707
|
-
var tooltipContent = obj ? accessorFn__default["default"](state["".concat(obj.type.toLowerCase(), "Label")])(obj.d) || '' : '';
|
|
1622
|
+
var tooltipContent = obj ? accessorFn(state["".concat(obj.type.toLowerCase(), "Label")])(obj.d) || '' : '';
|
|
1708
1623
|
toolTipElem.style.visibility = tooltipContent ? 'visible' : 'hidden';
|
|
1709
|
-
toolTipElem.innerHTML = tooltipContent;
|
|
1624
|
+
toolTipElem.innerHTML = tooltipContent;
|
|
1710
1625
|
|
|
1626
|
+
// set pointer if hovered object is clickable
|
|
1711
1627
|
state.canvas.classList[obj && state["on".concat(objType, "Click")] || !obj && state.onBackgroundClick ? 'add' : 'remove']('clickable');
|
|
1712
1628
|
state.hoverObj = obj;
|
|
1713
1629
|
}
|
|
1714
|
-
|
|
1715
1630
|
doRedraw && refreshShadowCanvas();
|
|
1716
1631
|
}
|
|
1717
|
-
|
|
1718
1632
|
if (doRedraw) {
|
|
1719
1633
|
// Wipe canvas
|
|
1720
|
-
clearCanvas(ctx, state.width, state.height);
|
|
1634
|
+
clearCanvas(ctx, state.width, state.height);
|
|
1721
1635
|
|
|
1636
|
+
// Frame cycle
|
|
1722
1637
|
var globalScale = d3Zoom.zoomTransform(state.canvas).k;
|
|
1723
1638
|
state.onRenderFramePre && state.onRenderFramePre(ctx, globalScale);
|
|
1724
1639
|
state.forceGraph.globalScale(globalScale).tickFrame();
|
|
1725
1640
|
state.onRenderFramePost && state.onRenderFramePost(ctx, globalScale);
|
|
1726
1641
|
}
|
|
1727
|
-
|
|
1728
|
-
TWEEN__default["default"].update(); // update canvas animation tweens
|
|
1642
|
+
TWEEN.update(); // update canvas animation tweens
|
|
1729
1643
|
|
|
1730
1644
|
state.animationFrameRequestId = requestAnimationFrame(animate);
|
|
1731
1645
|
})();
|