feat: horizontal
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
97c0adaa3b
commit
bbf5770828
98
index.html
98
index.html
@ -38,15 +38,22 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Space-Themed Continuous Heatmap</h2>
|
<h2>Live Activity</h2>
|
||||||
|
|
||||||
|
<div class="divider"></div>
|
||||||
|
|
||||||
|
|
||||||
<div id="chart"></div>
|
<div id="chart"></div>
|
||||||
<div id="legend" class="legend"></div>
|
<div id="legend" class="legend"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const horizontal = true;
|
||||||
|
const categoryAmount = 5;
|
||||||
|
|
||||||
// Dimensions
|
// Dimensions
|
||||||
const margin = { top: 20, right: 20, bottom: 20, left: 50 };
|
const margin = { top: 20, right: 20, bottom: 20, left: 50 };
|
||||||
const width = 800 - margin.left - margin.right;
|
const width = 800 - margin.left - margin.right;
|
||||||
const height = 500 - margin.top - margin.bottom;
|
const height = 85 * categoryAmount / 2 - margin.top - margin.bottom;
|
||||||
|
|
||||||
// Categories with labels
|
// Categories with labels
|
||||||
const categories = [
|
const categories = [
|
||||||
@ -60,7 +67,7 @@
|
|||||||
{ id: 7, label: "Refund Processed", color: "#A9A9A9" },
|
{ id: 7, label: "Refund Processed", color: "#A9A9A9" },
|
||||||
{ id: 8, label: "Subscription Renewed", color: "#BDB76B" },
|
{ id: 8, label: "Subscription Renewed", color: "#BDB76B" },
|
||||||
{ id: 9, label: "Feedback Submitted", color: "#00FFFF" },
|
{ id: 9, label: "Feedback Submitted", color: "#00FFFF" },
|
||||||
];
|
].filter((c) => c.id < categoryAmount);
|
||||||
|
|
||||||
// Store last intensity for each category
|
// Store last intensity for each category
|
||||||
const lastIntensity = new Map(categories.map(c => [c.id, Math.random()]));
|
const lastIntensity = new Map(categories.map(c => [c.id, Math.random()]));
|
||||||
@ -84,13 +91,26 @@
|
|||||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||||
|
|
||||||
// Time scales
|
// Time scales
|
||||||
const y = d3.scaleTime()
|
var x, y;
|
||||||
.domain([new Date(Date.now() - 60000), new Date()]) // Past 1 min to now
|
if (horizontal) {
|
||||||
.range([height, 0]);
|
x = d3.scaleTime()
|
||||||
|
.domain([new Date(Date.now() - 60000), new Date()]) // Past 1 min to now
|
||||||
|
.range([width, 0]);
|
||||||
|
|
||||||
const x = d3.scaleBand()
|
y = d3.scaleBand()
|
||||||
.domain(categories.map(c => c.id)) // Category IDs
|
.domain(categories.map(c => c.id)) // Category IDs
|
||||||
.range([0, width]);
|
.range([0, height]);
|
||||||
|
} else {
|
||||||
|
y = d3.scaleTime()
|
||||||
|
.domain([new Date(Date.now() - 60000), new Date()]) // Past 1 min to now
|
||||||
|
.range([height, 0]);
|
||||||
|
|
||||||
|
x = d3.scaleBand()
|
||||||
|
.domain(categories.map(c => c.id)) // Category IDs
|
||||||
|
.range([0, width]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Heatmap group
|
// Heatmap group
|
||||||
const grid = svg.append("g");
|
const grid = svg.append("g");
|
||||||
@ -99,23 +119,43 @@
|
|||||||
function updateHeatmap(data) {
|
function updateHeatmap(data) {
|
||||||
const cells = grid.selectAll("rect").data(data, d => d.id);
|
const cells = grid.selectAll("rect").data(data, d => d.id);
|
||||||
|
|
||||||
// Enter new data
|
if (horizontal) {
|
||||||
cells.enter()
|
cells.enter()
|
||||||
.append("rect")
|
.append("rect")
|
||||||
.attr("x", d => x(d.category))
|
.attr("y", d => y(d.category))
|
||||||
.attr("width", x.bandwidth())
|
.attr("width", 12)
|
||||||
.attr("y", d => y(new Date(d.timestamp)))
|
.attr("x", d => x(new Date(d.timestamp)))
|
||||||
.attr("height", 4) // Minimized spacing between blocks
|
.attr("height", 25) // Minimized spacing between blocks
|
||||||
.attr("fill", d => categories[d.category].color)
|
.attr("fill", d => categories[d.category].color)
|
||||||
.attr("opacity", d => d.intensity)
|
.attr("opacity", d => d.intensity)
|
||||||
.merge(cells) // Merge updates
|
.merge(cells) // Merge updates
|
||||||
.attr("y", d => y(new Date(d.timestamp)))
|
.attr("x", d => x(new Date(d.timestamp)))
|
||||||
.attr("opacity", d => d.intensity)
|
.attr("opacity", d => d.intensity)
|
||||||
.attr("visibility", d =>
|
.attr("visibility", d =>
|
||||||
y(new Date(d.timestamp)) >= 0 && y(new Date(d.timestamp)) <= height
|
x(new Date(d.timestamp)) >= 0 && x(new Date(d.timestamp)) <= width
|
||||||
? "visible"
|
? "visible"
|
||||||
: "hidden"
|
: "hidden"
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// Enter new data
|
||||||
|
cells.enter()
|
||||||
|
.append("rect")
|
||||||
|
.attr("x", d => x(d.category))
|
||||||
|
.attr("width", x.bandwidth())
|
||||||
|
.attr("y", d => y(new Date(d.timestamp)))
|
||||||
|
.attr("height", 4) // Minimized spacing between blocks
|
||||||
|
.attr("fill", d => categories[d.category].color)
|
||||||
|
.attr("opacity", d => d.intensity)
|
||||||
|
.merge(cells) // Merge updates
|
||||||
|
.attr("y", d => y(new Date(d.timestamp)))
|
||||||
|
.attr("opacity", d => d.intensity)
|
||||||
|
.attr("visibility", d =>
|
||||||
|
y(new Date(d.timestamp)) >= 0 && y(new Date(d.timestamp)) <= height
|
||||||
|
? "visible"
|
||||||
|
: "hidden"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Remove old data that moves off the screen
|
// Remove old data that moves off the screen
|
||||||
cells.exit().remove();
|
cells.exit().remove();
|
||||||
@ -162,7 +202,11 @@
|
|||||||
// Update the domain of the y-axis
|
// Update the domain of the y-axis
|
||||||
const currentTime = new Date();
|
const currentTime = new Date();
|
||||||
const pastTime = new Date(currentTime.getTime() - 60000);
|
const pastTime = new Date(currentTime.getTime() - 60000);
|
||||||
y.domain([pastTime, currentTime]);
|
if (horizontal) {
|
||||||
|
x.domain([pastTime, currentTime]);
|
||||||
|
} else {
|
||||||
|
y.domain([pastTime, currentTime]);
|
||||||
|
}
|
||||||
|
|
||||||
// Update positions of all heatmap cells
|
// Update positions of all heatmap cells
|
||||||
updateHeatmap(allData);
|
updateHeatmap(allData);
|
||||||
|
Loading…
Reference in New Issue
Block a user