feat: pretty close
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
e424fa2d03
commit
97c0adaa3b
46
index.html
46
index.html
@ -3,9 +3,15 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Live Heatmap with Intensity</title>
|
<title>Space-Themed Heatmap</title>
|
||||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||||
<style>
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
display: block;
|
display: block;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
@ -13,12 +19,15 @@
|
|||||||
|
|
||||||
.legend {
|
.legend {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend-item {
|
.legend-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend-color {
|
.legend-color {
|
||||||
@ -29,7 +38,7 @@
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Live Heatmap with Intensity</h2>
|
<h2>Space-Themed Continuous Heatmap</h2>
|
||||||
<div id="chart"></div>
|
<div id="chart"></div>
|
||||||
<div id="legend" class="legend"></div>
|
<div id="legend" class="legend"></div>
|
||||||
|
|
||||||
@ -41,16 +50,16 @@
|
|||||||
|
|
||||||
// Categories with labels
|
// Categories with labels
|
||||||
const categories = [
|
const categories = [
|
||||||
{ id: 0, label: "User Onboarded", color: "#1f77b4" },
|
{ id: 0, label: "User Onboarded", color: "#FFD700" },
|
||||||
{ id: 1, label: "Payment Accepted", color: "#ff7f0e" },
|
{ id: 1, label: "Payment Accepted", color: "#00BFFF" },
|
||||||
{ id: 2, label: "Payment Failed", color: "#d62728" },
|
{ id: 2, label: "Payment Failed", color: "#FF4500" },
|
||||||
{ id: 3, label: "Product Added to Cart", color: "#9467bd" },
|
{ id: 3, label: "Product Added to Cart", color: "#9400D3" },
|
||||||
{ id: 4, label: "Checkout Started", color: "#2ca02c" },
|
{ id: 4, label: "Checkout Started", color: "#32CD32" },
|
||||||
{ id: 5, label: "Order Placed", color: "#8c564b" },
|
{ id: 5, label: "Order Placed", color: "#8B4513" },
|
||||||
{ id: 6, label: "Order Cancelled", color: "#e377c2" },
|
{ id: 6, label: "Order Cancelled", color: "#FF69B4" },
|
||||||
{ id: 7, label: "Refund Processed", color: "#7f7f7f" },
|
{ id: 7, label: "Refund Processed", color: "#A9A9A9" },
|
||||||
{ id: 8, label: "Subscription Renewed", color: "#bcbd22" },
|
{ id: 8, label: "Subscription Renewed", color: "#BDB76B" },
|
||||||
{ id: 9, label: "Feedback Submitted", color: "#17becf" },
|
{ id: 9, label: "Feedback Submitted", color: "#00FFFF" },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Store last intensity for each category
|
// Store last intensity for each category
|
||||||
@ -96,7 +105,7 @@
|
|||||||
.attr("x", d => x(d.category))
|
.attr("x", d => x(d.category))
|
||||||
.attr("width", x.bandwidth())
|
.attr("width", x.bandwidth())
|
||||||
.attr("y", d => y(new Date(d.timestamp)))
|
.attr("y", d => y(new Date(d.timestamp)))
|
||||||
.attr("height", 5) // Fixed height for heatmap blocks
|
.attr("height", 4) // 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
|
||||||
@ -114,12 +123,12 @@
|
|||||||
|
|
||||||
// Real-time simulation
|
// Real-time simulation
|
||||||
let allData = [];
|
let allData = [];
|
||||||
const scrollingSpeed = 10; // Pixels per second
|
const scrollingSpeed = 20; // Pixels per second
|
||||||
|
|
||||||
function generateData() {
|
function generateData() {
|
||||||
// Simulate sporadic events with intensity
|
// Simulate sporadic events with intensity
|
||||||
const newData = categories.map(c => {
|
const newData = categories.map(c => {
|
||||||
if (Math.random() < 0.5) return null; // 50% chance no data for this category
|
if (Math.random() < 0.7) return null; // 70% chance no data for this category
|
||||||
const newIntensity = Math.random(); // Random intensity
|
const newIntensity = Math.random(); // Random intensity
|
||||||
const smoothIntensity = d3.interpolate(lastIntensity.get(c.id), newIntensity)(0.5); // Smooth transition
|
const smoothIntensity = d3.interpolate(lastIntensity.get(c.id), newIntensity)(0.5); // Smooth transition
|
||||||
lastIntensity.set(c.id, smoothIntensity); // Update last intensity
|
lastIntensity.set(c.id, smoothIntensity); // Update last intensity
|
||||||
@ -144,8 +153,8 @@
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const delta = now - lastTimestamp;
|
const delta = now - lastTimestamp;
|
||||||
|
|
||||||
// Generate data periodically (every 1 second)
|
// Generate data periodically (every 500ms for more activity)
|
||||||
if (delta >= 1000) {
|
if (delta >= 500) {
|
||||||
generateData();
|
generateData();
|
||||||
lastTimestamp = now;
|
lastTimestamp = now;
|
||||||
}
|
}
|
||||||
@ -161,4 +170,3 @@
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user