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

如何用D3.js生成指定范围的二维数组并绘制平滑曲线?

解决D3.js生成平滑曲线数据的问题

嗨,别担心,新手刚开始摸D3.js总会有点懵,这太正常啦!我来帮你一步步搞定曲线数据生成的部分,再把它和你现有的绘图代码结合起来~

第一步:整理参数+编写数据生成函数

首先咱们把你的参数表转成JavaScript数组,再写个函数,根据每个对象的alpha、beta、spend生成对应的[x,y]二维数组。

注意公式里的2.71828是自然常数e的近似值,直接用JS内置的Math.exp()计算会更准确,所以公式可以写成:
y = alpha * (1 - Math.exp(-beta * x))

另外BAN3的alpha是-,你得确认这个值应该填啥(比如0或者其他有效数值),我在代码里加了判断,遇到缺失的alpha会跳过这条数据并给你提示。

// 把参数表转换成JS数组
const curveParams = [
  { name: "BAN1", alpha: 140.3, beta: 3.86e-5, max_x_val: 28675.00, spend: 29919.00 },
  { name: "BAN2", alpha: 115.31, beta: 2.08e-5, max_x_val: 32302.00, spend: 28367.00 },
  { name: "BAN3", alpha: "-", beta: 5.07e-5, max_x_val: 19740.00, spend: 16972.00 },
  { name: "ADJ4", alpha: 91.8, beta: 0.000029119, max_x_val: 25855.00, spend: 27112.00 },
  { name: "ADJ5", alpha: 90.3, beta: 2.81e-5, max_x_val: 25793.00, spend: 23883.00 }
];

// 生成单条曲线的[x,y]数据函数
function generateCurveData(params) {
  // 处理alpha缺失/无效的情况
  if (params.alpha === "-" || typeof params.alpha !== "number") {
    console.warn(`跳过${params.name}:alpha值缺失或无效,请确认参数`);
    return null;
  }
  
  // 生成x序列:从0到spend,步长100(包含spend本身)
  const xValues = d3.range(0, params.spend + 100, 100);
  
  // 计算对应y值,生成二维数组
  return xValues.map(x => {
    const y = params.alpha * (1 - Math.exp(-params.beta * x));
    return [x, y];
  });
}

// 为每个参数对象生成曲线数据,过滤掉无效条目
const allCurveData = curveParams.map(params => ({
  name: params.name,
  data: generateCurveData(params)
})).filter(item => item.data !== null);

第二步:结合现有D3代码绘制多条平滑曲线

接下来把生成的数据和你原有的绘图代码结合,修改后可以绘制多条曲线,每条用不同颜色,同时保留你想要的动画效果:

$( document ).ready(function() {
  // 定义平滑曲线生成器
  var bezierLine = d3.svg.line()
    .x(function(d) { 
      // 把x数据映射到SVG宽度范围内(留20px边距)
      const maxX = d3.max(allCurveData.flatMap(item => item.data.map(d => d[0])));
      return d3.scale.linear().domain([0, maxX]).range([20, 280])(d[0]);
    })
    .y(function(d) { 
      // 把y数据映射到SVG高度范围内(SVG的y轴是从上到下,所以反转range)
      const maxY = d3.max(allCurveData.flatMap(item => item.data.map(d => d[1])));
      return d3.scale.linear().domain([0, maxY]).range([130, 20])(d[1]);
    })
    .interpolate("basis");

  var svg = d3.select("#bezier-demo")
    .append("svg")
    .attr("width", 300)
    .attr("height", 150);

  // 绘制每条曲线并添加动画
  svg.selectAll("path")
    .data(allCurveData)
    .enter()
    .append('path')
    .attr("d", function(d) { return bezierLine(d.data); })
    .attr("stroke", function(d, i) { 
      // 用D3内置颜色比例尺生成不同颜色
      return d3.scale.category10()(i); 
    })
    .attr("stroke-width", 1)
    .attr("fill", "none")
    .transition()
    .duration(2000)
    .attrTween("stroke-dasharray", function() {
      var len = this.getTotalLength();
      return function(t) {
        return (d3.interpolateString("0," + len, len + ",0"))(t);
      };
    });
});

几个关键细节说明:

  • 比例尺转换:你的x值(比如29919)远大于SVG宽度(300),必须用d3.scale.linear()把数据值映射到画布像素范围内,不然曲线会超出画布看不到。
  • alpha缺失处理:代码里加了警告提示,你替换掉BAN3的"-"为有效数值后,就能正常生成它的曲线。
  • 多曲线区分:用d3.scale.category10()自动生成不同颜色,方便区分每条曲线对应的对象。

这样你就能得到和Excel里一样的平滑曲线啦!如果要调整比例尺范围、动画时长这类细节,直接修改对应参数就行~

内容的提问来源于stack exchange,提问作者Gerle Batde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:18:56