-
Notifications
You must be signed in to change notification settings - Fork 248
/
Copy pathindex.html
68 lines (54 loc) · 2.42 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<head>
<style> body { margin: 0; } </style>
<script src="//unpkg.com/force-graph"></script>
<!--<script src="../../dist/force-graph.js"></script>-->
</head>
<body>
<div id="graph"></div>
<script>
fetch('../datasets/miserables.json').then(res => res.json()).then(data => {
const Graph = new ForceGraph(document.getElementById('graph'))
.graphData(data)
.nodeId('id')
.nodeLabel('id')
.nodeAutoColorBy('group')
.linkCanvasObjectMode(() => 'after')
.linkCanvasObject((link, ctx) => {
const MAX_FONT_SIZE = 4;
const LABEL_NODE_MARGIN = Graph.nodeRelSize() * 1.5;
const start = link.source;
const end = link.target;
// ignore unbound links
if (typeof start !== 'object' || typeof end !== 'object') return;
// calculate label positioning
const textPos = Object.assign(...['x', 'y'].map(c => ({
[c]: start[c] + (end[c] - start[c]) / 2 // calc middle point
})));
const relLink = { x: end.x - start.x, y: end.y - start.y };
const maxTextLength = Math.sqrt(Math.pow(relLink.x, 2) + Math.pow(relLink.y, 2)) - LABEL_NODE_MARGIN * 2;
let textAngle = Math.atan2(relLink.y, relLink.x);
// maintain label vertical orientation for legibility
if (textAngle > Math.PI / 2) textAngle = -(Math.PI - textAngle);
if (textAngle < -Math.PI / 2) textAngle = -(-Math.PI - textAngle);
const label = `${link.source.id} > ${link.target.id}`;
// estimate fontSize to fit in link length
ctx.font = '1px Sans-Serif';
const fontSize = Math.min(MAX_FONT_SIZE, maxTextLength / ctx.measureText(label).width);
ctx.font = `${fontSize}px Sans-Serif`;
const textWidth = ctx.measureText(label).width;
const bckgDimensions = [textWidth, fontSize].map(n => n + fontSize * 0.2); // some padding
// draw text label (with background rect)
ctx.save();
ctx.translate(textPos.x, textPos.y);
ctx.rotate(textAngle);
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fillRect(- bckgDimensions[0] / 2, - bckgDimensions[1] / 2, ...bckgDimensions);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = 'darkgrey';
ctx.fillText(label, 0, 0);
ctx.restore();
});
});
</script>
</body>