2012-12-06 29 views
1

正如標題所述,我創建了D3線/面積圖,我發現很難讓圖的寬度保持不變,這取決於我給出的數據量它渲染時,它會相應地縮放圖形的寬度,但我不確定如何讓它保持恆定的寬度,而不管給定的數據量如何,這是我想實現的。D3線圖沒有填充整個svg寬度

我想它與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/

謝謝!

回答

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 by mbostock描述我所指的「一般更新模式」。部分IIIII然後繼續解釋如何工作轉換到這種模式。

+0

感謝您的詳細解答! :)有一點讓我困惑,雖然我指定了一個固定的寬度,但圖表從來沒有填滿整個容器,我知道它會縮放,但是如果它不能將圖形放大到寬度和高度,我會給它?我認爲這是非常不一致的,儘管它是有道理的,但它在試圖實現數據集之間的一致性時會產生一個真正的問題。所以,如果我正確地理解了你,我的代碼應該會產生一個圖形,以適應我指定它使用的整個寬度。 – Odyss3us

+0

是不是因爲你減去了保證金? –

+0

如果只是它會「拉伸」域值,以某種理智的方式。結果根本沒有模式。有時候,較大的值會得到一個瘦的結果,而較小的值會得到一個寬的結果有時候情況恰恰相反。應該發生什麼,最長的條被設置爲最大寬度,並且所有其他比例都按比例縮放。 – JosephK