iamvisual/index.html

112 lines
3.5 KiB
HTML
Raw Normal View History

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Live Timeline Heatmap</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.heatmap rect {
//stroke: #aaa;
}
</style>
</head>
<body>
<h2>Live Timeline Heatmap</h2>
<div id="chart"></div>
<script>
// Configuration
const width = 500;
const height = 500;
const numCols = 10; // Number of columns
const numRows = 20; // Number of rows
const cellWidth = width / numCols; // Cell width
const cellHeight = height / numRows; // Cell height
const fadeOutRate = 0.8; // Intensity decay
const maxIntensity = 10; // Maximum intensity value
// Create SVG
const svg = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("class", "heatmap");
// Initialize grid
let grid = Array.from({ length: numRows }, () =>
Array.from({ length: numCols }, () => 0)
);
// Color scale
const colorScale = d3.scaleSequential(d3.interpolateTurbo).domain([0, maxIntensity]);
// Create grid rectangles
svg.selectAll("rect")
.data(grid.flat())
.enter()
.append("rect")
.attr("x", (_, i) => (i % numCols) * cellWidth)
.attr("y", (_, i) => Math.floor(i / numCols) * cellHeight)
.attr("width", cellWidth)
.attr("height", cellHeight)
.attr("fill", colorScale(0));
// Function to update the heatmap
function updateHeatmap() {
// Decay old values
for (let row of grid) {
for (let col = 0; col < row.length; col++) {
row[col] *= fadeOutRate;
}
}
// Update heatmap colors
svg.selectAll("rect")
.data(grid.flat())
.transition()
.duration(200)
.attr("fill", d => colorScale(d));
}
// Scroll rows upward and add a new empty row at the bottom
function scrollHeatmap() {
grid.shift(); // Remove the top row
grid.push(Array.from({ length: numCols }, () => 0)); // Add an empty row at the bottom
// Update grid positions
svg.selectAll("rect")
.data(grid.flat())
.transition()
.duration(200)
.attr("y", (_, i) => Math.floor(i / numCols) * cellHeight);
}
// Function to add events to the bottom row
function addEvent(col, intensity) {
if (col >= 0 && col < numCols) {
grid[grid.length - 1][col] = Math.min(
grid[grid.length - 1][col] + intensity,
maxIntensity
);
}
}
// Simulate incoming events
setInterval(() => {
const randomCol = Math.floor(Math.random() * numCols);
const randomIntensity = Math.random() * 8 + 2; // Random intensity (2-10)
addEvent(randomCol, randomIntensity);
}, 300); // Events every 300ms
// Animation loop
d3.interval(() => {
scrollHeatmap();
updateHeatmap();
}, 500); // Updates every 500ms
</script>
</body>
</html>