在数据可视化领域,D3.js 仍是当下最强大的 JavaScript 库之一,本文将以 D3.js v4 版本为基础,手把手教您实现一个专业级折线图,该图表将包含完整的坐标系、响应式设计、数据点交互等核心功能,并提供可直接运行的代码示例。
引入最新稳定版 D3.js v4
<script src="https://d3js.org/d3.v4.min.js"></script>
创建基础 HTML 结构
<div class="chart-container"> <svg id="lineChart"></svg> </div>
const margin = { top: 30, right: 40, bottom: 50, left: 60 }; const width = 800 - margin.left - margin.right; const height = 500 - margin.top - margin.bottom;
const xScale = d3.scaleTime() .domain(d3.extent(data, d => d.date)) .range([0, width]); const yScale = d3.scaleLinear() .domain([0, d3.max(data, d => d.value)]) .nice() .range([height, 0]);
const lineGenerator = d3.line() .x(d => xScale(d.date)) .y(d => yScale(d.value)) .curve(d3.curveMonotoneX); // 平滑曲线处理
const xAxis = d3.axisBottom(xScale) .tickFormat(d3.timeFormat("%Y-%m")); const yAxis = d3.axisLeft(yScale) .ticks(6);
const dots = svg.selectAll(".dot") .data(data) .enter().append("circle") .attr("class", "data-point") .attr("cx", d => xScale(d.date)) .attr("cy", d => yScale(d.value)) .attr("r", 4) .style("opacity", 0) .on("mouseover", function(event, d) { d3.select(this) .transition() .duration(200) .attr("r", 6) .style("opacity", 1); tooltip.style("visibility", "visible") .html(`日期:${d3.timeFormat("%Y年%m月")(d.date)}<br>数值:${d.value}`); }) .on("mousemove", function(event) { tooltip.style("top", (event.pageY - 10) + "px") .style("left", (event.pageX + 10) + "px"); }) .on("mouseout", function() { d3.select(this) .transition() .duration(200) .attr("r", 4) .style("opacity", 0); tooltip.style("visibility", "hidden"); });
function resizeChart() { const containerWidth = d3.select(".chart-container").node().getBoundingClientRect().width; width = containerWidth - margin.left - margin.right; xScale.range([0, width]); yScale.range([height, 0]); svg.attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); // 更新图表元素 svg.select(".line-path").attr("d", lineGenerator); svg.select(".x-axis").call(xAxis); svg.select(".y-axis").call(yAxis); } window.addEventListener("resize", resizeChart);
.chart-container { max-width: 1200px; margin: 2rem auto; background: #f8f9fa; padding: 20px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .data-point { fill: #4e79a7; stroke: white; stroke-width: 2; } .line-path { fill: none; stroke: #e15759; stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
数据完整性校验
console.assert(data.length > 0, "数据集不能为空"); console.assert(data.every(d => d.date instanceof Date), "日期字段必须为Date对象");
异常边界处理
try { // 图表初始化代码 } catch (error) { console.error("图表渲染失败:", error); d3.select("#lineChart") .append("text") .text("图表加载失败,请刷新重试") .attr("text-anchor", "middle") .attr("x", width/2) .attr("y", height/2); }
数据说明
示例数据应采用标准时间序列格式:
const sampleData = [ { date: new Date("2024-01"), value: 24 }, { date: new Date("2024-02"), value: 31 }, // ...其他数据点 ];
技术引用