You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于textarea输入的D3.js多折线图实现:nest()函数应用疑问

基于Textarea输入的D3.js多折线图实现方案

你的代码目前仅支持单折线绘制,因为mainData函数只提取了每行的x和第一个y值,而Excel粘贴的每行包含多个y系列数据(示例中每行是x、y1、y2)。要实现多折线,需要调整数据结构,并使用D3的分组功能(D3 v7推荐用d3.group替代旧版的nest)。


修改后的JavaScript代码

function mainData() {
  // 处理textarea输入,将每行数据转换为多系列数据点
  return document.getElementById('dinput').value.trim().split('\n').flatMap(line => {
    const tokens = line.trim().split(/\s+/).map(str => Number(str, 10));
    const x = tokens[0];
    // 从第2个元素开始,每个值对应一个系列
    return tokens.slice(1).map((y, index) => ({
      x: x,
      y: y,
      series: `系列${index + 1}` // 给每个系列命名
    }));
  });
}

// 优化事件监听:直接监听input事件(粘贴操作会触发input)
document.getElementById('dinput').addEventListener('input', function () {
  d3.select(".chart").remove();
  draw();
});

function draw() {
  const dataset = mainData();
  // 按series分组,得到每个系列的点数组
  const groupedData = d3.group(dataset, d => d.series);
  
  // 定义比例尺:使用所有数据的范围
  const xAccessor = d => d.x;
  const yAccessor = d => d.y;
  const dimensions = { width: 1280, height: 720, margins: 50 };
  dimensions.ctrWidth = dimensions.width - dimensions.margins * 2;
  dimensions.ctrHeight = dimensions.height - dimensions.margins * 2;

  const svg = d3.select('#chartdiv')
    .append("svg")
    .classed("chart", true)
    .attr("viewBox", `0 0 ${dimensions.width} ${dimensions.height}`);

  const ctr = svg.append("g")
    .attr("transform", `translate(${dimensions.margins}, ${dimensions.margins})`);

  // 计算x和y的全局范围
  const xDomain = d3.extent(dataset, xAccessor);
  const yDomain = d3.extent(dataset, yAccessor);

  const xScale = d3.scaleLinear()
    .domain(xDomain)
    .range([0, dimensions.ctrWidth])
    .nice();

  const yScale = d3.scaleLinear()
    .domain(yDomain)
    .range([dimensions.ctrHeight, 0])
    .nice();

  // 创建颜色比例尺,区分不同系列
  const colorScale = d3.scaleOrdinal()
    .domain(Array.from(groupedData.keys()))
    .range(d3.schemeCategory10); // 使用D3内置的分类色板

  // 创建线生成器
  const lineGenerator = d3.line()
    .x(d => xScale(xAccessor(d)))
    .y(d => yScale(yAccessor(d)))
    .curve(d3.curveMonotoneX); // 可选:添加平滑曲线

  // 绘制每条折线
  groupedData.forEach((seriesData, seriesName) => {
    ctr.append('path')
      .datum(seriesData)
      .attr('d', lineGenerator)
      .attr('fill', 'none')
      .attr('stroke', colorScale(seriesName))
      .attr('stroke-width', 2)
      .attr('data-series', seriesName); // 给路径添加系列标识,方便后续样式控制
  });

  // 绘制坐标轴
  ctr.append('g').call(d3.axisLeft(yScale));
  ctr.append('g')
    .style('transform', `translateY(${dimensions.ctrHeight}px)`)
    .call(d3.axisBottom(xScale));

  // 可选:添加图例
  const legend = ctr.append('g')
    .attr('transform', `translate(${dimensions.ctrWidth - 150}, 20)`);

  Array.from(groupedData.keys()).forEach((seriesName, index) => {
    const legendRow = legend.append('g')
      .attr('transform', `translate(0, ${index * 20})`);

    legendRow.append('rect')
      .attr('width', 15)
      .attr('height', 15)
      .attr('fill', colorScale(seriesName));

    legendRow.append('text')
      .attr('x', 20)
      .attr('y', 12)
      .style('font-size', '12px')
      .text(seriesName);
  });
}

// 初始绘制
draw();

修改后的HTML代码

<textarea id="dinput" rows="15" cols="60">
280	0.013	0.013
290	0.035	0.013
300	0.140	0.013
310	0.425	0.313
320	0.820	0.013
330	1.152	0.013
340	0.802	0.013
350	0.423	0.013
360	0.123	0.013
370	0.040	0.013
380	0.020	0.013
390	0.020	0.831
400	0.020	0.013
410	0.020	0.013
420	0.015	0.013
</textarea>
<div id="chartdiv"></div>

<script src="https://d3js.org/d3.v7.min.js"></script>

关键实现步骤说明

  1. 数据结构转换:

    • 使用flatMap将每行的多个y值拆分为多个数据对象,每个对象包含x、y和series(系列名称),确保每条折线的所有点带有统一的系列标识。
  2. 数据分组:

    • 用d3.group(dataset, d => d.series)替代旧版nest,按系列名称分组数据,得到键为系列名、值为对应数据点数组的Map结构。
  3. 全局比例尺计算:

    • x和y轴比例尺基于所有数据的范围,确保所有折线能完整显示在图表内。
  4. 多折线绘制:

    • 遍历分组后的每个系列,调用线生成器绘制对应路径,用分类色板区分不同系列。
  5. 事件监听优化:

    • 移除嵌套事件绑定,直接监听textarea的input事件(粘贴操作会自动触发input),避免重复绑定导致的多次绘制问题。
  6. 可选图例添加:

    • 基于分组的系列名生成图例,方便区分不同折线对应的系列。

内容的提问来源于stack exchange,提问作者Dheeraj Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 11:01:08