iamvisual/index.html

111 lines
3.7 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 Heatmap with Smooth Scrolling</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
svg {
display: block;
margin: auto;
}
</style>
</head>
<body>
<h2>Live Heatmap with Smooth Scrolling</h2>
<div id="chart"></div>
<script>
// 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;
// Create SVG
const svg = d3.select("#chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.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]);
const x = d3.scaleBand()
.domain(d3.range(10)) // Example: 10 categories
.range([0, width]);
// Heatmap color scale
const colorScale = d3.scaleSequential(d3.interpolateYlOrRd)
.domain([0, 100]); // Adjust for event intensity
// Axis
const yAxis = svg.append("g")
.attr("class", "y-axis")
.call(d3.axisLeft(y).ticks(20));
const grid = svg.append("g");
// Initialize heatmap
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", 5) // Fixed height for heatmap blocks
.attr("fill", d => colorScale(d.value))
.merge(cells) // Merge updates
.transition()
.duration(500)
.attr("y", d => y(new Date(d.timestamp)))
.attr("visibility", d =>
y(new Date(d.timestamp)) >= 0 && y(new Date(d.timestamp)) <= height
? "visible"
: "hidden"
); // Hide items out of bounds
// Remove old data that moves off the screen
cells.exit().remove();
// Shift all cells upward to simulate scrolling
grid.selectAll("rect")
.transition()
.duration(500)
.attr("y", d => y(new Date(d.timestamp)));
}
// Simulate real-time updates
let allData = [];
setInterval(() => {
// Generate random data
const newData = Array.from({ length: 10 }, (_, i) => ({
id: `${Date.now()}-${i}`,
category: i,
timestamp: Date.now(),
value: Math.random() * 100,
}));
// Add new data to the global array and keep only recent data
allData = [...allData, ...newData].filter(d =>
new Date(d.timestamp) >= new Date(Date.now() - 60000)
);
// Update time scale domain
y.domain([new Date(Date.now() - 60000), new Date()]);
yAxis.transition().duration(500).call(d3.axisLeft(y).ticks(20));
// Update heatmap with filtered data
updateHeatmap(allData);
}, 1000);
</script>
</body>
</html>