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>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Space-Themed Continuous Heatmap</h2>
|
||||
<h2>Live Activity</h2>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
|
||||
<div id="chart"></div>
|
||||
<div id="legend" class="legend"></div>
|
||||
|
||||
<script>
|
||||
const horizontal = true;
|
||||
const categoryAmount = 5;
|
||||
|
||||
// Dimensions
|
||||
const margin = { top: 20, right: 20, bottom: 20, left: 50 };
|
||||
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
|
||||
const categories = [
|
||||
@ -60,7 +67,7 @@
|
||||
{ id: 7, label: "Refund Processed", color: "#A9A9A9" },
|
||||
{ id: 8, label: "Subscription Renewed", color: "#BDB76B" },
|
||||
{ id: 9, label: "Feedback Submitted", color: "#00FFFF" },
|
||||
];
|
||||
].filter((c) => c.id < categoryAmount);
|
||||
|
||||
// Store last intensity for each category
|
||||
const lastIntensity = new Map(categories.map(c => [c.id, Math.random()]));
|
||||
@ -84,13 +91,26 @@
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// Time scales
|
||||
const y = d3.scaleTime()
|
||||
.domain([new Date(Date.now() - 60000), new Date()]) // Past 1 min to now
|
||||
.range([height, 0]);
|
||||
var x, y;
|
||||
if (horizontal) {
|
||||
x = d3.scaleTime()
|
||||
.domain([new Date(Date.now() - 60000), new Date()]) // Past 1 min to now
|
||||
.range([width, 0]);
|
||||
|
||||
const x = d3.scaleBand()
|
||||
.domain(categories.map(c => c.id)) // Category IDs
|
||||
.range([0, width]);
|
||||
y = d3.scaleBand()
|
||||
.domain(categories.map(c => c.id)) // Category IDs
|
||||
.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
|
||||
const grid = svg.append("g");
|
||||
@ -99,23 +119,43 @@
|
||||
function updateHeatmap(data) {
|
||||
const cells = grid.selectAll("rect").data(data, d => d.id);
|
||||
|
||||
// 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"
|
||||
);
|
||||
if (horizontal) {
|
||||
cells.enter()
|
||||
.append("rect")
|
||||
.attr("y", d => y(d.category))
|
||||
.attr("width", 12)
|
||||
.attr("x", d => x(new Date(d.timestamp)))
|
||||
.attr("height", 25) // Minimized spacing between blocks
|
||||
.attr("fill", d => categories[d.category].color)
|
||||
.attr("opacity", d => d.intensity)
|
||||
.merge(cells) // Merge updates
|
||||
.attr("x", d => x(new Date(d.timestamp)))
|
||||
.attr("opacity", d => d.intensity)
|
||||
.attr("visibility", d =>
|
||||
x(new Date(d.timestamp)) >= 0 && x(new Date(d.timestamp)) <= width
|
||||
? "visible"
|
||||
: "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
|
||||
cells.exit().remove();
|
||||
@ -162,7 +202,11 @@
|
||||
// Update the domain of the y-axis
|
||||
const currentTime = new Date();
|
||||
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
|
||||
updateHeatmap(allData);
|
||||
|
Loading…
Reference in New Issue
Block a user