D3选择/附加SVG的更改顺序

时间:2019-05-06 09:34:44

标签: javascript d3.js

我已经创建了一个点阵视觉效果,如下面的代码片段所示。彩色圆圈表示值,灰色圆圈表示空/未使用。例如,在我的案例中,这三种颜色以百分比形式表示来自三个国家(美国,加拿大和墨西哥)的项目资金。灰色代表尚未筹集的资金,也采用百分比形式。

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'];

这种方法困扰着我,我不知道为什么。我希望有一种更复杂的方法。

1 个答案:

答案 0 :(得分:1)

您的代码中,该顺序与circData相同。

但是实际上您是通过cxcy而不是它们的顺序来控制位置的。


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>