我已经创建了一个点阵视觉效果,如下面的代码片段所示。彩色圆圈表示值,灰色圆圈表示空/未使用。例如,在我的案例中,这三种颜色以百分比形式表示来自三个国家(美国,加拿大和墨西哥)的项目资金。灰色代表尚未筹集的资金,也采用百分比形式。
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 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 data = [
{'country':'USA', 'value':.20},
{'country':'Canada', 'value':.15},
{'country':'Mexico', 'value':.10}
];
var circArray = new Array(50);
var circPercentage = 100/circArray.length;
var circData = new Array;
data.forEach(function(item) {
for (var i =0; i <item.value*100/circPercentage; i++) {
circData.push(item.country);
}
});
var arrayDiff = 50-circData.length;
for (var i=0; i <(arrayDiff); i++) {
circData.push("");
}
//console.log(circData)
var maxColumn = 10;
var colorMap = {
'USA':"#f6d18b",
'Canada':"#366092",
'Mexico':"#95b3d7",
"":"#a6a6a6"
};
var xScale = d3.scaleLinear()
.range([0,width])
.domain([0,1]);
var yScale = d3.scaleLinear()
.range([height,0])
.domain([0,1]);
graphGroup.selectAll('circle')
.data(circData)
.enter()
.append('circle')
.attr('cx', function(d, i) {
return (i % maxColumn) * 30
})
.attr('cy', function(d, i) {
return ~~((i / maxColumn) % maxColumn) * 30
})
.attr('r', 10)
.style('fill', function(d) {
//console.log(d)
return colorMap[d];
});
<script src="https://d3js.org/d3.v5.min.js"></script>
我使用.forEach()
和for循环的工作是因为我创建了一个正确长度的数组,以将圆映射到百分比逻辑,如下所示:
['USA','USA','USA','USA','USA','USA','USA','USA','USA','USA', ... , "", "", ""];
但是我找不到要添加圆圈的方向/顺序的文档。假设我想要上面片段的相反部分,其中灰色圆圈显示在顶部,彩色圆圈从底部开始?还是假设我想在左侧使用灰色圆圈,在右侧使用彩色圆圈?
是否有直接方法来切换svg元素的方向/顺序?还是我唯一选择转置数据本身?如:
["","","",... 'USA','USA','USA','USA','USA','USA','USA','USA','USA','USA'];
这种方法困扰着我,我不知道为什么。我希望有一种更复杂的方法。
答案 0 :(得分:1)
在您的代码中,该顺序与circData
相同。
但是实际上您是通过cx
和cy
而不是它们的顺序来控制位置的。
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 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 data = [
{'country':'USA', 'value':.20},
{'country':'Canada', 'value':.15},
{'country':'Mexico', 'value':.10}
];
var circArray = new Array(50);
var circPercentage = 100/circArray.length;
var circData = new Array;
data.forEach(function(item) {
for (var i =0; i <item.value*100/circPercentage; i++) {
circData.push(item.country);
}
});
var arrayDiff = 50-circData.length;
for (var i=0; i <(arrayDiff); i++) {
circData.push("");
}
circData.reverse() //<---------------------------
//console.log(circData)
var maxColumn = 10;
var colorMap = {
'USA':"#f6d18b",
'Canada':"#366092",
'Mexico':"#95b3d7",
"":"#a6a6a6"
};
var xScale = d3.scaleLinear()
.range([0,width])
.domain([0,1]);
var yScale = d3.scaleLinear()
.range([height,0])
.domain([0,1]);
graphGroup.selectAll('circle')
.data(circData)
.enter()
.append('circle')
.attr('cx', function(d, i) {
return (i % maxColumn) * 30
})
.attr('cy', function(d, i) {
return ~~((i / maxColumn) % maxColumn) * 30
})
.attr('r', 10)
.style('fill', function(d) {
//console.log(d)
return colorMap[d];
});
<script src="https://d3js.org/d3.v5.min.js"></script>