D3.js(Data-Driven Documents)是当前最流行的数据可视化JavaScript库之一,被《纽约时报》、NASA等权威机构广泛使用,折线图作为其核心图表类型,能清晰展示时间序列数据趋势,适用于金融分析、物联网监控等专业场景。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v7.min.js"></script> <style> .axis path { stroke: #555; } .line { fill: none; stroke: steelblue; stroke-width: 2; } </style> </head> <body> <div id="chart"></div> <script src="chart.js"></script> </body> </html>
// chart.js const dataset = [ { date: "2025-01", value: 30 }, { date: "2025-02", value: 80 }, { date: "2025-03", value: 45 }, // ...其他数据点 ];
// 设置画布尺寸(遵循响应式设计原则) const width = 800, height = 500; const margin = { top: 20, right: 30, bottom: 40, left: 50 }; // 创建SVG容器 const svg = d3.select("#chart") .append("svg") .attr("width", width) .attr("height", height); // 时间解析器(ISO 8601格式处理) const parseTime = d3.timeParse("%Y-%m"); // 比例尺配置(线性比例尺+时间比例尺) const xScale = d3.scaleTime() .domain(d3.extent(dataset, d => parseTime(d.date))) .range([margin.left, width - margin.right]); const yScale = d3.scaleLinear() .domain([0, d3.max(dataset, d => d.value)]) .range([height - margin.bottom, margin.top]); // 轴线生成器 const xAxis = d3.axisBottom(xScale).ticks(5); const yAxis = d3.axisLeft(yScale).ticks(5); // 绘制轴线 svg.append("g") .attr("class", "x axis") .attr("transform", `translate(0,${height - margin.bottom})`) .call(xAxis); svg.append("g") .attr("class", "y axis") .attr("transform", `translate(${margin.left},0)`) .call(yAxis); // 折线生成器(贝塞尔曲线插值) const line = d3.line() .x(d => xScale(parseTime(d.date))) .y(d => yScale(d.value)) .curve(d3.curveMonotoneX); // 绘制路径 svg.append("path") .datum(dataset) .attr("class", "line") .attr("d", line);
// 添加数据点标记 svg.selectAll(".dot") .data(dataset) .enter().append("circle") .attr("class", "dot") .attr("cx", d => xScale(parseTime(d.date))) .attr("cy", d => yScale(d.value)) .attr("r", 4) .style("fill", "#4682b4"); // 添加鼠标悬停提示 const tooltip = d3.select("body").append("div") .attr("class", "tooltip") .style("position", "absolute") .style("opacity", 0) .style("background", "#fff") .style("padding", "8px") .style("border-radius", "4px") .style("box-shadow", "0 2px 4px rgba(0,0,0,0.2)"); svg.selectAll(".dot") .on("mouseover", (event, d) => { tooltip.transition().duration(200).style("opacity", .9); tooltip.html(`日期:${d.date}<br>数值:${d.value}`) .style("left", (event.pageX + 10) + "px") .style("top", (event.pageY - 28) + "px"); }) .on("mouseout", () => { tooltip.transition().duration(500).style("opacity", 0); });
window.addEventListener('resize', () => { // 重新计算比例尺和更新图表 });