-
Notifications
You must be signed in to change notification settings - Fork 1
/
node.label.ts
93 lines (75 loc) · 2.77 KB
/
node.label.ts
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { Settings } from 'sigma/settings';
import { NodeDisplayData, PartialButFor } from 'sigma/types';
const PADDING = 4;
function splitLabel(label) {
return label.replace(/.{10}\S*\s+/g, "$&|").split(/\s+\|/);
}
function biggestPiece(pieces) {
let big = "";
pieces.filter(piece => big.length < piece.length ? big = piece : null);
return big;
}
function drawLabel(
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, 'x' | 'y' | 'size' | 'label' | 'color'>,
settings: Settings
): void {
if (!data.label) return;
const size = data.labelSize || settings.labelSize;
const font = settings.labelFont;
const weight = settings.labelWeight;
const color = data.labelColor || settings.labelColor.color;
const pieces = splitLabel(data.label);
const x = data.x + data.size + 3;
let y = data.y + size / (pieces.length > 1 ? 2 : 3);
context.fillStyle = color;
context.font = `${weight} ${size}px ${font}`;
const lineHeight = size + PADDING;
if (pieces.length > 1)
y -= lineHeight * pieces.length / 3;
pieces.forEach((piece, i) =>
context.fillText(piece, x, y + i * lineHeight)
);
}
function drawHover(
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, 'x' | 'y' | 'size' | 'label' | 'color'>,
settings: Settings
): void {
const size = data.labelSize || settings.labelSize;
const font = settings.labelFont;
const weight = settings.labelWeight;
const pieces = data.label ? splitLabel(data.label) : [];
data = { ...data, label: data.label || data.hoverLabel };
context.font = `${weight} ${size}px ${font}`;
// Then we draw the label background
context.fillStyle = "#555";
context.beginPath();
if (!data.label)
context.arc(data.x, data.y, data.size + PADDING / 2, 0, Math.PI * 2);
else {
const textWidth = context.measureText(biggestPiece(pieces)).width;
const boxWidth = Math.round(textWidth + 5);
const boxHeight = Math.round(pieces.length * (size + PADDING) + PADDING);
const radius = Math.max(data.size + PADDING, boxHeight / 2);
const angleRadian = Math.asin(boxHeight / 2 / radius);
const xShift = Math.sqrt(
Math.abs(Math.pow(radius, 2) - Math.pow(boxHeight / 2, 2))
),
xMin = data.x + xShift,
xMax = data.x + data.size + PADDING + boxWidth - boxHeight / 4,
yMin = data.y - boxHeight / 2,
yMax = data.y + boxHeight / 2;
context.moveTo(xMin, yMax);
context.lineTo(xMax, yMax);
context.arc(xMax, data.y, boxHeight /2, -Math.PI / 2, Math.PI / 2);
context.lineTo(xMax, yMin);
context.lineTo(xMin, yMin);
context.arc(data.x, data.y, radius, angleRadian, -angleRadian);
}
context.closePath();
context.fill();
// And finally we draw the label
drawLabel(context, data, settings);
}
export { drawLabel, drawHover };