a multi-line chart sample code using d3.js
This commit is contained in:
188
d3.html
Normal file
188
d3.html
Normal file
@@ -0,0 +1,188 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>D3.js Multiple Line Chart</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
|
||||
.line { fill: none; stroke-width: 2px; }
|
||||
.axis { font-size: 12px; }
|
||||
.legend { font-size: 12px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input type="file" id="fileInput" accept=".json" />
|
||||
<div id="chart"></div>
|
||||
|
||||
<script>
|
||||
// Sample multiple dataset
|
||||
const data = [
|
||||
{
|
||||
name: 'Temperature',
|
||||
color: 'steelblue',
|
||||
values: [
|
||||
{date: '2023-01-01', value: 32},
|
||||
{date: '2023-02-01', value: 35},
|
||||
{date: '2023-03-01', value: 40},
|
||||
{date: '2023-04-01', value: 45},
|
||||
{date: '2023-05-01', value: 50}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Rainfall',
|
||||
color: 'green',
|
||||
values: [
|
||||
{date: '2023-01-01', value: 10},
|
||||
{date: '2023-02-01', value: 15},
|
||||
{date: '2023-03-01', value: 20},
|
||||
{date: '2023-04-01', value: 25},
|
||||
{date: '2023-05-01', value: 30}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Render multiple line chart
|
||||
function renderMultiLineChart(datasets) {
|
||||
// Clear previous chart
|
||||
d3.select("#chart").html("");
|
||||
|
||||
// Chart dimensions
|
||||
const margin = {top: 50, right: 100, bottom: 50, left: 50};
|
||||
const width = 700 - margin.left - margin.right;
|
||||
const height = 400 - margin.top - margin.bottom;
|
||||
|
||||
// Tooltip
|
||||
const tooltip = d3.select("body")
|
||||
.append("div")
|
||||
.attr("class", "tooltip")
|
||||
.style("opacity", 0);
|
||||
|
||||
// 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})`);
|
||||
|
||||
// Parse dates
|
||||
const parseTime = d3.timeParse("%Y-%m-%d");
|
||||
const formatTime = d3.timeFormat("%Y-%m-%d");
|
||||
datasets.forEach(series => {
|
||||
series.values.forEach(d => {
|
||||
d.date = parseTime(d.date);
|
||||
});
|
||||
});
|
||||
|
||||
// Combine all values for scale
|
||||
const allValues = datasets.flatMap(series => series.values.map(d => d.value));
|
||||
|
||||
// Scales
|
||||
const x = d3.scaleTime()
|
||||
.domain(d3.extent(datasets[0].values, d => d.date))
|
||||
.range([0, width]);
|
||||
|
||||
const y = d3.scaleLinear()
|
||||
.domain([
|
||||
d3.min(allValues) * 0.9,
|
||||
d3.max(allValues) * 1.1
|
||||
])
|
||||
.range([height, 0]);
|
||||
|
||||
// Line generator
|
||||
const line = d3.line()
|
||||
.x(d => x(d.date))
|
||||
.y(d => y(d.value));
|
||||
|
||||
// X-axis
|
||||
svg.append("g")
|
||||
.attr("class", "axis")
|
||||
.attr("transform", `translate(0,${height})`)
|
||||
.call(d3.axisBottom(x));
|
||||
|
||||
// Y-axis
|
||||
svg.append("g")
|
||||
.attr("class", "axis")
|
||||
.call(d3.axisLeft(y));
|
||||
|
||||
// Lines and data points for each dataset
|
||||
datasets.forEach(series => {
|
||||
// Line
|
||||
svg.append("path")
|
||||
.datum(series.values)
|
||||
.attr("class", "line")
|
||||
.attr("fill", "none")
|
||||
.attr("stroke", series.color)
|
||||
.attr("stroke-width", 2)
|
||||
.attr("d", line);
|
||||
|
||||
// Data points
|
||||
svg.selectAll(`.dot-${series.name}`)
|
||||
.data(series.values)
|
||||
.enter().append("circle")
|
||||
.attr("class", `dot dot-${series.name}`)
|
||||
.attr("cx", d => x(d.date))
|
||||
.attr("cy", d => y(d.value))
|
||||
.attr("r", 5)
|
||||
.attr("fill", series.color)
|
||||
.on("mouseover", (event, d) => {
|
||||
tooltip.transition()
|
||||
.duration(200)
|
||||
.style("opacity", .9);
|
||||
tooltip.html(`
|
||||
<strong>${series.name}</strong><br>
|
||||
Date: ${formatTime(d.date)}<br>
|
||||
Value: ${d.value}
|
||||
`)
|
||||
.style("left", (event.pageX + 10) + "px")
|
||||
.style("top", (event.pageY - 28) + "px");
|
||||
})
|
||||
.on("mouseout", () => {
|
||||
tooltip.transition()
|
||||
.duration(500)
|
||||
.style("opacity", 0);
|
||||
});
|
||||
});
|
||||
|
||||
// Legend
|
||||
const legend = svg.selectAll(".legend")
|
||||
.data(datasets)
|
||||
.enter().append("g")
|
||||
.attr("class", "legend")
|
||||
.attr("transform", (d, i) => `translate(${width + 10},${i * 20})`);
|
||||
|
||||
legend.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("width", 10)
|
||||
.attr("height", 10)
|
||||
.style("fill", d => d.color);
|
||||
|
||||
legend.append("text")
|
||||
.attr("x", 20)
|
||||
.attr("y", 9)
|
||||
.text(d => d.name)
|
||||
.style("text-anchor", "start");
|
||||
}
|
||||
|
||||
// Render chart
|
||||
renderMultiLineChart(data);
|
||||
// File input handler
|
||||
document.getElementById('fileInput').addEventListener('change', function(e) {
|
||||
const file = e.target.files[0];
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function(event) {
|
||||
try {
|
||||
const jsonData = JSON.parse(event.target.result);
|
||||
renderMultiLineChart(jsonData);
|
||||
} catch (error) {
|
||||
alert('Error parsing JSON file: ' + error);
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
35
datasets.json
Normal file
35
datasets.json
Normal file
@@ -0,0 +1,35 @@
|
||||
[
|
||||
{
|
||||
"name": "Temperature",
|
||||
"color": "steelblue",
|
||||
"values": [
|
||||
{"date": "2023-01-01", "value": 32},
|
||||
{"date": "2023-02-01", "value": 35},
|
||||
{"date": "2023-03-01", "value": 40},
|
||||
{"date": "2023-04-01", "value": 45},
|
||||
{"date": "2023-05-01", "value": 50}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Temperature2",
|
||||
"color": "red",
|
||||
"values": [
|
||||
{"date": "2023-01-01", "value": 35},
|
||||
{"date": "2023-02-01", "value": 40},
|
||||
{"date": "2023-03-01", "value": 45},
|
||||
{"date": "2023-04-01", "value": 50},
|
||||
{"date": "2023-05-01", "value": 32}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Temperature3",
|
||||
"color": "green",
|
||||
"values": [
|
||||
{"date": "2023-01-01", "value": 40},
|
||||
{"date": "2023-02-01", "value": 45},
|
||||
{"date": "2023-03-01", "value": 50},
|
||||
{"date": "2023-04-01", "value": 32},
|
||||
{"date": "2023-05-01", "value": 35}
|
||||
]
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user