1

タイトルにあるように、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);

}

</p>

フィドルだけでなくhttp://jsfiddle.net/JL33M/

ありがとうございました!

4

1 に答える 1

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()

このmbostock によるチュートリアルでは、私が参照している「一般的な更新パターン」について説明しています。パートIIとパートIIIは、このパターンへのトランジションの操作方法の説明に進みます。

于 2012-12-06T20:11:30.917 に答える