-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmerzCake.html
145 lines (120 loc) · 5.55 KB
/
merzCake.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
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<!DOCTYPE html>
<html>
<head>
</head>
<body style="background-color:#333; padding:0; margin:0">
<script>
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
// Need to recalculate this when window size is not sufficient
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext('2d');
// Define the node colors for all nodes and the central node
const nodeColors = ['#ef476f', '#ffd166', '#06d6a0', '#118ab2'];
// Define the central node and its position and set initial heights
const centralNode = {x: 400, y: 300, heights: [0, 0, 0, 0]};
// Define the nodes dynamically
const nodesData = [
{ x: 100, y: 100, heights: [20, 15, 15, 5] },
{ x: 1100, y: 550, heights: [10, 35, 15, 35] },
{ x: 100, y: 500, heights: [15, 35, 55, 0] },
{ x: 800, y: 900, heights: [0, 35, 0, 5] },
{ x: 200, y: 750, heights: [50, 0, 25, 5] },
{ x: 800, y: 100, heights: [10, 35, 15, 11] },
{ x: 300, y: 400, heights: [5, 25, 20, 15] }
];
// Calculate the width for each node based on the total height (this needs to take into account area and be completely redone)
const calculateWidth = (heights) => {
const totalHeight = heights.reduce((acc, height) => acc + height, 0);
const nodeSize = 100; // Desired node size
return (totalHeight / nodeSize) * nodeSize;
};
// Calculate the central node's heights based on the sum of nodes
centralNode.heights = nodesData.reduce((acc, node) => node.heights.map((h, i) => acc[i] + h), centralNode.heights);
const drawNode = (node, x, y, colors) => {
const totalHeight = node.heights.reduce((acc, height) => acc + height, 0);
const sectionHeight = calculateWidth(node.heights) / totalHeight;
let currentY = y;
// Create a clipping path as a circle with a larger radius
ctx.save();
ctx.beginPath();
const radius = calculateWidth(node.heights) / 2;
ctx.arc(x + radius, y + radius, radius, 0, Math.PI * 2);
ctx.clip();
// Add a black outline border around the central node
if (node === centralNode) {
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.stroke();
}
node.heights.forEach((height, index) => {
ctx.fillStyle = colors[index];
ctx.fillRect(x, currentY, calculateWidth(node.heights), height * sectionHeight);
currentY += height * sectionHeight;
// Add data labels for sections with values >= 15
if (height >= 15) {
const sectionLabelX = x + calculateWidth(node.heights) / 2;
const sectionLabelY = currentY - (height * sectionHeight) / 2.5;
ctx.fillStyle = '#333';
ctx.font = 'bold 15px Arial';
ctx.textAlign = 'center';
ctx.fillText(height, sectionLabelX, sectionLabelY);
}
});
// Restore the context to remove the clipping path
ctx.restore();
// Add a total label
const labelX = x + calculateWidth(node.heights) / 2;
const labelY = y - 10; // Position the label above the node
ctx.fillStyle = '#3e9c35';
ctx.font = 'bold 24px Arial';
ctx.textAlign = 'center';
ctx.fillText("$" + totalHeight + "k", labelX, labelY);
};
// Draw lines from each node to the central node
const drawLines = () => {
nodesData.forEach(nodeData => {
const centerX = nodeData.x + calculateWidth(nodeData.heights) / 2;
const centerY = nodeData.y + calculateWidth(nodeData.heights) / 2;
const centralX = centralNode.x + calculateWidth(centralNode.heights) / 2;
const centralY = centralNode.y + calculateWidth(centralNode.heights) / 2;
// Draw lines from each node to the central node
ctx.beginPath();
ctx.setLineDash([8, 5]);
ctx.moveTo(centerX, centerY);
ctx.lineTo(centralX, centralY);
ctx.strokeStyle = '#999';
ctx.lineWidth = 1;
ctx.stroke();
});
};
// Draw the nodes and lines
const drawNodes = () => {
nodesData.forEach((nodeData, index) => {
drawNode(nodeData, nodeData.x, nodeData.y, nodeColors);
});
};
// Draw the central node
const drawCentralNode = () => {
drawNode(centralNode, centralNode.x, centralNode.y, nodeColors);
// Draw a black outline around the central node
const radius = calculateWidth(centralNode.heights) / 2;
const centralX = centralNode.x + radius;
const centralY = centralNode.y + radius;
ctx.beginPath();
ctx.arc(centralX, centralY, radius, 0, Math.PI * 2);
ctx.strokeStyle = '#fff';
ctx.lineWidth = 4;
ctx.setLineDash([0, 0]);
ctx.stroke();
};
// Draw lines connecting nodes to the central node
drawLines();
// Draw the nodes and lines
drawNodes();
// Draw the central node
drawCentralNode();
</script>
</body>
</html>