[英]D3.js looping through an array of objects
我正在嘗試根據標題制作一排高度和寬度相等的條形圖。 有一個100個對象的數組,每個對象包含一個稱為result的鍵 ,它本身和其他20個對象的數組,因此最終結果必須是一行2000條,但是我只能得到20條:
Codepen: https ://codepen.io/ekilja01/pen/RdJqGO
數據是一個對象數組,具有一個稱為result的對象數組,格式如下:
0:
page: 1
results: Array(20)
0: {vote_count: 17968, id: 19995, video: false, vote_average: 7.4, title: "Avatar", …}
...
length: 20
1: {page: 2, total_results: 406130, total_pages: 20307, results: Array(20)}
2: {page: 3, total_results: 406130, total_pages: 20307, results: Array(20)}
這是我的方法:
d3.json('data.json').then(data => {
console.log(data);
for (let i = 0; i < data.length; i++) {
//x and y domain
xScale.domain(data[i].results.map(d => d.title));
yScale.domain(data[i].results.map(d => d.original_title));
svg.selectAll('rect')
.data(data[i].results)
.enter()
.append('rect')
.style('fill', 'red')
.attr('width', xScale.bandwidth())
.attr('height', 70)
.attr('x', function (d) {
return xScale(d.title);
})
.attr('y', function (d) {
return yScale.bandwidth() + 175;
});
}
}).catch(error => console.log(error));
精美的問題描述和CodePen-輕松幫助您!
我已經為您的CodePen鏈接做了一個稍微修改的版本
基本上,發生的事情是,對於for循環中的每個迭代,您都將選擇前x個(在您的情況下為20個)匹配的rect
元素。 這意味着在第一次迭代之后,每次迭代都將使用當前迭代的20個數據條目替換與相同的20個rect
元素的數據綁定。
我進行了兩種更改來解決此問題:
svg.selectAll('rect')
更改為svg.selectAll('.rect_${i}')
,這將選擇具有相應類( .rect_0
, .rect_1
等)的所有元素。 這樣做可以防止覆蓋先前的rect
元素。 .attr('x')
的回調函數中添加+ xScale.range()[1] * i
。 這會將每20個rect
元素向右移動,以確保rect
元素不會相互繪制。 但是,要點2確實可以繪制出非常寬的圖表。 如果您希望各行之間彼此相鄰,我使用rect
元素的高度添加了功能(在注釋中)。
讓我知道這是否對您有幫助!
在循環中,僅在循環中第一次添加元素:數據數組中有20個項目,svg中沒有矩形,因此輸入了全部20個項目。 第二次在數據數組中有20個項目,在svg中有20個矩形,因此enter選擇為空,新數據僅綁定到20個現有矩形。
作為其他答案的替代方法,您的數據似乎不是分層的,但是您具有分層的結構。 如果您的數據結構與DOM結構相同,那么這將更加簡單。 讓我們對數據進行一些重組:
var combined = [];
for (let i = 0; i < data.length; i++) {
combined.push(...data[i].results);
}
現在我們的數據是:
[
{vote_count: 17968, id: 19995, video: false, vote_average: 7.4, title: "Avatar", …,}
{...},
{...},
...
並且所有要映射的對象都在一個數組中,該數組中的一項,一個要添加到圖表中的元素。 現在我們可以做一個簡單的輸入循環:
svg.selectAll('rect')
.data(combined)
.enter()
.append('rect')
.style('fill', 'red')
.attr('width', xScale.bandwidth())
.attr('height', 70)
.attr('x', function (d) {
return xScale(d.title);
})
.attr('y', function (d) {
return yScale.bandwidth() + 175;
});
通常,如果需要循環以在DOM中輸入元素,則無需使用慣用的d3。 通過避免for循環輸入元素,縮放也變得更加容易,因為在遍歷父數組時我們不會不斷更新它。 比例域和范圍只需設置一次。
這是更新的codepen 。
現在,2000個元素將生成非常小的矩形,可能小於一個像素寬,我不確定為什么要像這樣縮放條形的高度,但這是不同的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.