使用相同的数据集绘制各种符号



我有一个看起来像这样的数据集:

var shapes = [
    {
        type: 'rect',       // which shape to draw
        size: [ 1, 100 ],   // width and height (for rect) or single number for lines, triangles or squares
        color: color[0],
        orientation: 0      // in degrees in interval [0, 360[
    },
    {
        type: 'triangle',
        size: 55,
        color: color[1],
        orientation: 0
    },
    {
        type: 'triangle',
        size: 96,
        color: color[0],
        orientation: 0
    }
    // etc …
]

我想做的是绘制数据集中的所有形状,数据集的长度可变,是随机生成的,由定义形状的不同对象中的各种属性定义。形状应均匀分布,且不得相互重叠。

数据绑定到周围的g元素,如下所示:

var viewport = d3.select('body').append('svg').selectAll('g').data(shapes)
var group = viewport.append('g')

我该如何用d3的方式处理这个问题?我试过shapes.filter(shape => shape.type === 'rect').forEach(/* ... */),但感觉我没有用d3的方式。感谢您提供有关如何处理此问题的任何线索!

我会使用路径,以及一个返回与d.type属性有关的路径的函数。

编辑:有点像这样,尽管你必须以某种方式指定你想要的符号的定位方式,因为在这个例子中,它们只会被画在彼此的顶部。

var drawers = {
  rect: function(d) {
    return 'M 0 0 l '+ d.size[0] + ' 0 l 0 ' + d.size[1] + ' l -' + d.size[0] + ' 0 l 0 -' + d.size[1];
  },
  triangle: function(d) {},
};
var g = d3.select('#mySvg').append('g');
var symbols = g.selectAll('.symbol')
  .data(shapes);
symbols.enter()
  .append('path')
  .classed('symbol', true)
  .attr({
    d: function(d) {return drawers[d.type](d);}
  });

最终的解决方案是使用d3.svg.symbol()构造函数(假设shapes是介绍性文章中描述的数组,type的细微差异是triangle-upcirclesquare:

const center = [ w / 2, h / 2 ]
const vis = d3.select(container)
  .append('svg')
  .attr('width', w)
  .attr('height', h)
const symbols = vis.selectAll('.symbol').data(shapes)
const getPathForShape = d => d3.svg.symbol().type(d.type).size(d.size)()
const paths = symbols.enter()
  .append('path')
  .classed('symbol', true)
  .attr('d', getPathForShape)
  .attr('fill', d => d.color)
  .attr('x', center[0])
  .attr('y', center[1])

然后使用力定向图()对其进行分布

const force = d3.layout.force()
  .size([w, h])
  .charge(-100)
  .nodes(shapes)
  .gravity(0.1)
  .on('tick', _ => paths.attr('transform', d =>
    'translate(' + d.x + ',' + d.y + ')'))
// simulate a static graph:
force.start()
for (var i = 0; i < 100; i++) force.tick()
force.stop()

最新更新