我试图将一些矩形的 x 和 y 坐标存储到一个数组中。有 20 个矩形,我将这些值存储在一个包含 20 个数组的数组中。数组中的每一项如下所示:
[
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0}
];
我在我的 rect append 中添加了一个 .each()
,如下所示:
.each(function(d,i) {
return polyMaster[i][0].y = d3.select(this).attr('y');
})
此时我注意到所有的 y
值都是相同的。我通过尝试确认了这一点:
.each(function(d,i) {
return polyMaster[i][0].y = i;
})
返回 19
-- 最后一个索引。所以看起来我以前所有的索引 y
都被新的覆盖了。
var margins = {top:20, bottom:300, left:30, right:100};
var height = 600;
var width = 900;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var outerRadius = (400 / 2);
var innerRadius = 15;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+ ")");
var heightScale = d3.scaleLinear()
.domain([.01,.09])
.range([7,50]);
var data = [{'manager': 'Mirae Asset', 'share': 0.016},
{'manager': 'Manulife', 'share': 0.015},
{'manager': 'ChinaAMC', 'share': 0.012},
{'manager': 'Principal', 'share': 0.015},
{'manager': 'Aberdeen Standard', 'share': 0.013},
{'manager': 'CSOP', 'share': 0.015},
{'manager': 'BOCI-Prudential', 'share': 0.019},
{'manager': 'Allianz', 'share': 0.016},
{'manager': 'HSBC', 'share': 0.027},
{'manager': 'Deutsche Bank', 'share': 0.014},
{'manager': 'Invesco', 'share': 0.025},
{'manager': 'First State', 'share': 0.033},
{'manager': 'JP Morgan', 'share': 0.041},
{'manager': 'Value Partners', 'share': 0.04},
{'manager': 'Schroders', 'share': 0.051},
{'manager': 'Hang Seng', 'share': 0.063},
{'manager': 'UBS', 'share': 0.056},
{'manager': 'SSgA', 'share': 0.066},
{'manager': 'Fidelity', 'share': 0.088},
{'manager': 'BlackRock', 'share': 0.084}];
var poly = [
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0}
];
var polyMaster = new Array(20).fill(poly);
var colorMap = {
'Fidelity':"#003366",
'BlackRock':"#366092",
'SSgA':"#4f81b9",
'Hang Seng':"#95b3d7",
'UBS':"#b8cce4",
'Schroders':"#e7eef8",
'JP Morgan':"#a6a6a6",
'Value Partners':"#d9d9d9",
'Yuanta':"#ffffcc",
'First State':"#ffffcc",
'HSBC':'#f6d18b',
'Invesco':'#e4a733',
'BOCI-Prudential':"#b29866",
'Allianz':'#a6a6a6',
'Mirae Asset':'#d9d9d9',
'Manulife':'#e7eef8',
'CSOP':'#b8cce4',
'Principal':'#95b3d7',
'Deutsche Bank':'#4f81b9',
'Aberdeen Standard':'#366092',
'ChinaAMC':'#003366'
};
var sortedData = data.sort(function(a,b) {
return b.share - a.share;
});
let counterRect = 0,
counterText = 0;
var column = graphGroup.selectAll('.ranks')
.data(sortedData)
.attr('class', 'ranks')
.enter().append("g");
column.append("rect")
.attr("width", 120)
.attr("height", function(d) {
return heightScale(d.share)
})
.attr('x', function(d) {return 0})
.attr('y', function(d, i) {
let previous = counterRect;
return (counterRect += heightScale(d.share)+2, previous)
})
.each(function(d,i) {
if (i>=0) {
return polyMaster[i][0].x = 120;
}
})
.each(function(d,i) {
if (i>=0) {
const index = i;
polyMaster[index][0].y = d3.select(this).attr('y');
}
})
.style('fill',function(d,i) {return colorMap[d.manager]});
column.append("text")
.attr('x', function(d) {return 60})
.attr('y', function(d, i) {
let previous = counterText;
return (counterText += heightScale(d.share)+2, previous + (heightScale(d.share)/2))
})
.attr("dominant-baseline", "central")
.attr('text-anchor', 'middle')
.text(function(d) {
return d.manager;
});
console.log(polyMaster)
<script src="https://d3js.org/d3.v5.min.js"></script>
问题
我如何迭代地存储我的矩形的 y
属性,但一次仍然是一个(以避免被覆盖)?
注意:我只是担心 x
和 y
的第一个对象。一旦我弄清楚如何执行上述操作,剩下的三个将在稍后映射出来。
最佳答案
您的问题与 d3.each
或其索引无关。你的问题出在这里:
var poly = [
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0}
];
var polyMaster = new Array(20).fill(poly);
所有数组中的所有对象都指向同一个对象(poly
)。改变一个就会改变所有。
一个快速修复方法是使用 JSON.parse
和 JSON.stringify
来复制对象:
var polyMaster = d3.range(20).map(()=>JSON.parse(JSON.stringify(poly)))
不过,还有几种选择。另一个简单的方法是直接在 map
中传递数组:
var polyMaster = d3.range(20).map(()=>[
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0}
])
此外,正如您注意到的,我使用的是 d3.range
而不是 new Array
+ fill
。
这里是修改后的代码:
var margins = {top:20, bottom:300, left:30, right:100};
var height = 600;
var width = 900;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var outerRadius = (400 / 2);
var innerRadius = 15;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+ ")");
var heightScale = d3.scaleLinear()
.domain([.01,.09])
.range([7,50]);
var data = [{'manager': 'Mirae Asset', 'share': 0.016},
{'manager': 'Manulife', 'share': 0.015},
{'manager': 'ChinaAMC', 'share': 0.012},
{'manager': 'Principal', 'share': 0.015},
{'manager': 'Aberdeen Standard', 'share': 0.013},
{'manager': 'CSOP', 'share': 0.015},
{'manager': 'BOCI-Prudential', 'share': 0.019},
{'manager': 'Allianz', 'share': 0.016},
{'manager': 'HSBC', 'share': 0.027},
{'manager': 'Deutsche Bank', 'share': 0.014},
{'manager': 'Invesco', 'share': 0.025},
{'manager': 'First State', 'share': 0.033},
{'manager': 'JP Morgan', 'share': 0.041},
{'manager': 'Value Partners', 'share': 0.04},
{'manager': 'Schroders', 'share': 0.051},
{'manager': 'Hang Seng', 'share': 0.063},
{'manager': 'UBS', 'share': 0.056},
{'manager': 'SSgA', 'share': 0.066},
{'manager': 'Fidelity', 'share': 0.088},
{'manager': 'BlackRock', 'share': 0.084}];
var poly = [
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0},
{'x':0,'y':0}
];
var polyMaster = d3.range(20).map(()=>JSON.parse(JSON.stringify(poly)))
var colorMap = {
'Fidelity':"#003366",
'BlackRock':"#366092",
'SSgA':"#4f81b9",
'Hang Seng':"#95b3d7",
'UBS':"#b8cce4",
'Schroders':"#e7eef8",
'JP Morgan':"#a6a6a6",
'Value Partners':"#d9d9d9",
'Yuanta':"#ffffcc",
'First State':"#ffffcc",
'HSBC':'#f6d18b',
'Invesco':'#e4a733',
'BOCI-Prudential':"#b29866",
'Allianz':'#a6a6a6',
'Mirae Asset':'#d9d9d9',
'Manulife':'#e7eef8',
'CSOP':'#b8cce4',
'Principal':'#95b3d7',
'Deutsche Bank':'#4f81b9',
'Aberdeen Standard':'#366092',
'ChinaAMC':'#003366'
};
var sortedData = data.sort(function(a,b) {
return b.share - a.share;
});
let counterRect = 0,
counterText = 0;
var column = graphGroup.selectAll('.ranks')
.data(sortedData)
.attr('class', 'ranks')
.enter().append("g");
column.append("rect")
.attr("width", 120)
.attr("height", function(d) {
return heightScale(d.share)
})
.attr('x', function(d) {return 0})
.attr('y', function(d, i) {
let previous = counterRect;
return (counterRect += heightScale(d.share)+2, previous)
})
.each(function(d,i) {
if (i>=0) {
return polyMaster[i][0].x = 120;
}
})
.each(function(d,i) {
if (i>=0) {
const index = i;
polyMaster[index][0].y = d3.select(this).attr('y');
}
})
.style('fill',function(d,i) {return colorMap[d.manager]});
column.append("text")
.attr('x', function(d) {return 60})
.attr('y', function(d, i) {
let previous = counterText;
return (counterText += heightScale(d.share)+2, previous + (heightScale(d.share)/2))
})
.attr("dominant-baseline", "central")
.attr('text-anchor', 'middle')
.text(function(d) {
return d.manager;
});
console.log(polyMaster)
<script src="https://d3js.org/d3.v5.min.js"></script>
关于javascript - d3.each() 一次存储一个值,而不是一次存储所有值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57388293/