【问题标题】:D3 line graph not filling entire svg widthD3折线图未填充整个svg宽度
【发布时间】:2012-12-06 19:40:21
【问题描述】:

正如标题所述,我创建了一个 D3 线/面积图,我发现很难让图表的宽度保持不变,这取决于我提供给它的要渲染的数据量,它会缩放宽度相应地绘制图表,但我不确定如何让它保持恒定的宽度,无论给定的数据量如何,这是我想要实现的。

我想这与 x 和 y 坐标的缩放有关,但我现在卡住了,似乎无法弄清楚它为什么这样做。

这是我到目前为止的代码,

  //dimensions and margins
  var width = 625,
  height = 350,
  margin = 5,

  // get the svg and set it's width/height
  svg = d3.select("#main")
    .attr("width", width)
    .attr("height", height);

  //initialize the graph
  init([
        [12345,42345,32345,22345,72345,62345,32345,92345,52345,22345], 
        [1234,4234,3234,2234,7234,6234,3234,9234,5234,2234] 
      ]);

  $("button").live('click', function(){
      var id = $(this).attr("id");
      if(id == "one"){
        updateGraph([
                [52345,32345,12345,22345,62345,72345,92345,32345,22345,22345,52345,32345,12345,22345,62345,72345,92345,32345,22345,22345,52345,32345,12345,22345,62345,72345,92345,32345,22345,22345], 
                [4234,12345,2234,32345,6234,7234,9234,3234,2234,2234,4234,1234,2234,3234,6234,7234,9234,3234,2234,2234,4234,1234,2234,3234,6234,7234,9234,3234,2234,2234] 
              ]);
      }else if(id == "two"){
        updateGraph([
              [12345,42345,32345,22345,72345,62345,32345,92345,52345,22345,12345,42345,32345,22345,72345,62345,32345,92345,52345,22345,12345,42345,32345,22345,72345], 
              [1234,2345,3234,2234,7234,6234,3234,9234,5234,2234,1234,4234,3234,2234,7234,6234,3234,9234,5234,2234,1234,4234,3234,2234,7234] 
            ]);
      }

  });

function init(data){

  var x = d3.scale.linear()
    .domain([0,data[0].length])
    .range([margin, width-margin]),

  y = d3.scale.linear()
    .domain([0,d3.max(data[0])])
    .range([height-margin, margin]),

  /* line path generator */
  line = d3.svg.line().interpolate('monotone')
    .x(function(d,i) { return x(i); })
    .y(function(d) { return y(d); }),

  /* area path generator */
  area = d3.svg.area().interpolate('monotone')
    .x(line.x())
    .y1(line.y())
    .y0(y(0)),

  groups = svg.selectAll("g")
    .data(data)
    .enter()
    .append("g");

  svg.select("g")
    .selectAll("circle")
  .data(data[0])
  .enter()
    .append("circle")
    .attr("class", "dot")
    .attr("cx", line.x())
    .attr("cy", line.y())
    .attr("r", 4);

  /* add the areas */
  groups.append("path")
    .attr("class", "area")
    .attr("d",area)
    .style("fill", function(d,i) { return (i == 0 ? "steelblue" : "red" ); });

  /* add the lines */
  groups.append("path")
    .attr("class", "line")
    .attr("d", line);
}

function updateGraph(data){

  var x = d3.scale.linear()
    .domain([0,data[0].length])
    .range([margin, width-margin]),

  y = d3.scale.linear()
    .domain([0,d3.max(data[0])])
    .range([height-margin, margin]),

  /* line path generator */
  line = d3.svg.line().interpolate('monotone')
    .x(function(d,i) { return x(i); })
    .y(function(d) { return y(d); }),

  /* area path generator */
  area = d3.svg.area().interpolate('monotone')
    .x(line.x())
    .y1(line.y())
    .y0(y(0));

  groups = svg.selectAll("g")
    .data(data),

  circles = svg.select("g")
    .selectAll("circle");

  circles.data(data[0])
      .exit().remove();

  circles.data(data[0])
    .enter().append("circle")
        .attr("class", "dot")
        .attr("cx", line.x())
        .attr("cy", line.y())
        .attr("r", 4);

  /* animate circles */
  circles.data(data[0])
    .transition()
    .duration(1000)
    .attr("cx", line.x())
    .attr("cy", line.y());

  /* animate the lines */
  groups.select('.line')
    .transition()
    .duration(1000)
    .attr("d",line);

  /* animate the areas */
  groups.select('.area')
    .transition()
    .duration(1000)
    .attr("d",area);

}

还有一把小提琴http://jsfiddle.net/JL33M/

谢谢!

【问题讨论】:

    标签: javascript jquery d3.js


    【解决方案1】:

    图表的宽度取决于你给它的range()range([0,100]) 将始终“拉伸”domain() 值以占用 100 个单位。

    这就是您的代码当前正在执行的操作:

    var x = d3.scale.linear()
      .domain([0,data[0].length])
      .range([margin, width-margin]);// <-- always a fixed width
    

    您希望宽度取决于数据条目的数量。假设您已经决定希望每个数据点占用 5 个单位,那么 range() 需要取决于数据集的大小:

    var x = d3.scale.linear()
      .domain([0,data[0].length])
      .range([margin, 5 * data[0].length]);// <-- 5 units per data point
    

    当然,在这些条件下,您的图形宽度会随着数据集而增长;如果你给它一个非常长的数据数组,比如 500 个点,那么图形将是 2500 个单位宽,并且可能会超出屏幕。但是如果你的数据是这样的,你知道它的最大长度,那么你会没事的。

    在不相关的说明中,我认为您的代码可以使用重构来减少重复性。您应该能够使用单个 update() 函数来实现您正在做的事情,而无需 init() 函数。

    This tutorial mbostock 描述了我所指的“一般更新模式”。部分IIIII 然后继续解释如何将转换转换为这种模式。

    【讨论】:

    • 感谢您的详细解答! :) 有一件事让我有点困惑,即使我指定了一个固定的宽度,图表也永远不会填满整个容器,我知道它可以缩放,但它不应该将图表缩放到我的宽度和高度给它?老实说,这是非常不一致的,即使它是有道理的,但在尝试实现数据集之间的一致性时会产生一个真正的问题。因此,如果我理解正确,我的代码应该会生成一个可以拉伸以适应我指定使用的整个宽度的图形?
    • 不是因为你在减去margin吗?
    • 如果它会以某种理智的方式“拉伸”域值。结果根本没有模式。有时较大的值会得到一个窄的结果,而较小的值会得到一个宽的结果。有时情况正好相反。应该发生的是,最长的条设置为最大宽度,所有其他条都按比例缩放。
    猜你喜欢
    • 2013-01-23
    • 1970-01-01
    • 2020-07-31
    • 2015-02-08
    • 2021-07-23
    • 2022-01-19
    • 2017-04-13
    • 2012-07-29
    • 2021-10-25
    相关资源
    最近更新 更多