2016-10-20 34 views
2

我使用this mbostock example作爲指南,但它在d3 v3中。我在第4版中已經讀過,選擇已經改變了,但這似乎不是我的問題,因爲數據從未改變 - 這是一個靜態圖表(現在)。d3 v4分組條形圖 - .data(fn).enter()爲空

我有對象的數組,其中,我希望爲每個對象創建一個組(g),和兩個矩形(rect)對於每個field1和對象相關聯的日期的field2。我可以創建組,但是當我嘗試製作矩形時,輸入組看起來是空的。

有人可以解釋爲什麼這是?

jsfiddle (not working)

UPDATE:jsfiddle (working)–由於@赫拉爾-朵

var models = [ 
    { 
    "date":"2016-10-13T07:00:00.000Z", 
    "field1":19, 
    "field2":83 
    }, 
    { 
    "date":"2016-10-14T07:00:00.000Z", 
    "field1":67, 
    "field2":93 
    }, 
    { 
    "date":"2016-10-15T07:00:00.000Z", 
    "field1":10, 
    "field2":56 
    }, 
    { 
    "date":"2016-10-16T07:00:00.000Z", 
    "field1":98, 
    "field2":43 
    } 
]; 
models = models.map(i => { 
    i.date = new Date(i.date); 
    return i; 
}); 

var container = d3.select('body'), 
    width = 500, 
    height = 300, 
    margin = {top: 30, right: 20, bottom: 30, left: 50}, 
    barPadding = .2, 
    axisTicks = {qty: 5, outerSize: 0, dateFormat: '%m-%d'}; 

var svg = container 
    .append("svg") 
    .attr("width", width) 
    .attr("height", height) 
    .append("g") 
    .attr("transform", `translate(${margin.left},${margin.top})`); 

var xScale0 = d3.scaleBand().range([0, width - margin.left - margin.right]).padding(barPadding); 
var xScale1 = d3.scaleBand(); 
var yScale = d3.scaleLinear().range([height - margin.top - margin.bottom, 0]); 

var xAxis = d3.axisBottom(xScale0).tickFormat(d3.timeFormat(axisTicks.dateFormat)).tickSizeOuter(axisTicks.outerSize); 
var yAxis = d3.axisLeft(yScale).ticks(axisTicks.qty).tickSizeOuter(axisTicks.outerSize); 

xScale0.domain(models.map(d => d.date)); 
xScale1.domain(['field1', 'field2']).range([0, xScale0.bandwidth()]); 
yScale.domain([0, d3.max(models, d => d.field1 > d.field2 ? d.field1 : d.field2)]); 

var date = svg.selectAll(".date") 
    .data(models) 
    .enter().append("g") 
    .attr("class", "date") 
    .attr("transform", d => `translate(${xScale0(d.date)},0)`); 

/* Add field1 bars */ 
var rect = date.selectAll(".bar") 
    .data(d => d) // FIXME: the .enter() group seems to contain nothing 
    .enter() 
    .append("rect") 
    .attr("class", "bar") 
    .attr("x", d => { xScale1('field1') }) 
    .attr("y", d => { yScale(d.field1) }) 
    .attr("width", xScale1.bandwidth()) 
    .attr("height", d => { 
    return height - margin.top - margin.bottom - yScale(d.field1) 
    }); 

/* Add field2 bars */ 
// var rect = date.selectAll(".bar") 
// .data(d => d) 
// .enter() 
// .append("rect") 
// .attr("class", "bar") 
// .attr("x", d => { xScale1('field2') }) 
// .attr("y", d => { yScale(d.field2) }) 
// .attr("width", xScale1.bandwidth()) 
// .attr("height", d => { 
// return height - margin.top - margin.bottom - yScale(d.field1) 
// }); 

// Add the X Axis 
svg.append("g") 
    .attr("class", "x axis") 
    .attr("transform", `translate(0,${height - margin.top - margin.bottom})`) 
    .call(xAxis); 

// Add the Y Axis 
svg.append("g") 
    .attr("class", "y axis") 
    .call(yAxis); 

回答

2

在D3,data必須是一個數組。如果你看看Bostock的例子,layers是一組數組。這是console.log(layers)結果:

Array[4] 
    0:Array[58] 
    1:Array[58] 
    2:Array[58] 
    3:Array[58] 

因此,由於layers是數組的數組,當在後面的代碼博斯托克寫入此:

.data(function(d) { return d; }) 

他將數組傳遞給data,其工作。

然而,在你的代碼,你傳遞一個對象data在您輸入的選擇爲rect

對象{日期和時間:週四2016年10月13日18:00:00 GMT + 1100,字段1: 19,FIELD2:83}

:傳遞數組到data。這是我做出的唯一改變:

.data(d => [d]) 

現在你有一個數組:

[{日期和時間:週四二○一六年十月一十三日18:00:00 GMT + 1100,字段1:19,場2: 83}]

這是你更新的提琴:https://jsfiddle.net/96d3wtys/

PS:你要調整你的酒吧的yheight

+0

優秀。謝謝!附註:你知道我如何結合59-83行嗎?我正在繪製一組條(field1),然後是另一個(field2)。如果重構原始數據使其更容易,那也沒關係。 – KFunk

+0

您可以使用組元素來避免冗餘代碼,但正如您所說,它涉及重構您的數據。所以,如果你不介意有點重複,那麼代碼似乎就像現在這樣好。 –