D3圆形包装,静态尺寸

时间:2018-04-14 02:45:22

标签: javascript d3.js

我正在尝试使用静态大小圆圈值来实现D3 pack layout,我希望D3能够处理刚放置,但我看到d3覆盖了提供的圆圈大小。我不确定如何保持从数据传递的相同大小。请参阅下面的代码,当我将标签为RAD的孩子的大小从100更改为5000时,我看到其他圈子的大小正在发生变化,我该如何制作要使用我从数据中获得的确切大小进行渲染的布局?请给我一些指针或jsfiddle

指向codepen的链接 - https://codepen.io/navinleon/pen/mxZJWr

提前致谢。

var w = 1000,
    h = 500;

var data = {
    name: "root",
    children: [{
        label: 'RAD',
        size: 100,
        color: '#c99700'
    }, {
        label: 'BIL',
        size: 100,
        color: '#008ce6'
    }, {
        label: 'EEN',
        size: 100,
        color: '#007377'
    }, {
        label: 'INO',
        size: 100,
        color: '#b4975a'
    }, ]
};

var canvas = d3.select("#canvas")
    .append("svg:svg")
    .attr('width', w)
    .attr('height', h);

var nodes = d3.layout.pack()
    .value(function (d) {
        return d.size;
    }).padding(100)
    .size([w, h])
    .nodes(data);

// Get rid of root node
nodes.shift();

canvas.selectAll('circles')
    .data(nodes)
    .enter()
    .append('svg:circle')
    .attr('cx', function (d) {
        return d.x;
    })
    .attr('cy', function (d) {
        return d.y;
    })
    .attr('r', function (d) {
        return d.r;
    })
    .attr('fill', function (d) {
        return d.color;
    });

2 个答案:

答案 0 :(得分:2)

使用d3.packSiblings():

实际上有一个方便的方法,名为d3.packSiblings,它似乎正是您需要(没有任何力模拟)来定位节点。

根据API

  

打包指定的圆圈数组,每个圆圈必须具有circle.r属性,指定圆的半径。

因此,将数据中的size属性更改为r,您只需要:

var packed = d3.packSiblings(data.children);

以下是演示:



var data = {
  name: "root",
  children: [{
    label: 'RAD',
    r: 50,
    color: '#c99700'
  }, {
    label: 'BIL',
    r: 75,
    color: '#008ce6'
  }, {
    label: 'EEN',
    r: 20,
    color: '#007377'
  }, {
    label: 'INO',
    r: 42,
    color: '#b4975a'
  }, ]
};

var packed = d3.packSiblings(data.children);

var w = 500,
  h = 400;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h)
  .append("g")
  .attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");

var color = d3.scaleOrdinal(d3.schemeCategory10);

var nodes = svg.selectAll(null)
  .data(data.children)
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", function(d) {
    return d.r
  })
  .style("fill", function(_, i) {
    return color(i)
  })

<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;

使用力模拟

您实际上不想要圈组布局。圆包布局必须适合pack.size数组指定区域内的所有圆圈。

因为你想设置圈子&#39;确定自己的尺寸,你希望D3只关注放置,我想到的最明显的选择是使用力模拟

在此提议的解决方案中,我们使用forceXforceY将焦点设置为SVG的中心。然后,我们将停止模拟并运行给定次数(所需的元素越少,您需要的迭代越少):

var simulation = d3.forceSimulation(data.children)
  .force("x", d3.forceX(w / 2))
  .force("y", d3.forceY(h / 2))
  .force("collide", d3.forceCollide(function(d) {
    return d.size
  }))
  .stop();

以下是一些演示。

首先,设置所有圈子&#39;半径为100:

&#13;
&#13;
var w = 500,
  h = 400;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var color = d3.scaleOrdinal(d3.schemeCategory10)

var data = {
  name: "root",
  children: [{
    label: 'RAD',
    size: 100,
    color: '#c99700'
  }, {
    label: 'BIL',
    size: 100,
    color: '#008ce6'
  }, {
    label: 'EEN',
    size: 100,
    color: '#007377'
  }, {
    label: 'INO',
    size: 100,
    color: '#b4975a'
  }, ]
};

var simulation = d3.forceSimulation(data.children)
  .force("x", d3.forceX(w / 2))
  .force("y", d3.forceY(h / 2))
  .force("collide", d3.forceCollide(function(d) {
    return d.size
  }))
  .stop();

for (var i = 0; i < 100; ++i) simulation.tick();

var nodes = svg.selectAll(null)
  .data(data.children)
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", function(d) {
    return d.size
  })
  .style("fill", function(_, i) {
    return color(i)
  })
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;

现在让我们将3个圆圈的大小减少到20:

&#13;
&#13;
var w = 500,
  h = 400;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var color = d3.scaleOrdinal(d3.schemeCategory10)

var data = {
  name: "root",
  children: [{
    label: 'RAD',
    size: 20,
    color: '#c99700'
  }, {
    label: 'BIL',
    size: 100,
    color: '#008ce6'
  }, {
    label: 'EEN',
    size: 20,
    color: '#007377'
  }, {
    label: 'INO',
    size: 20,
    color: '#b4975a'
  }, ]
};

var simulation = d3.forceSimulation(data.children)
  .force("x", d3.forceX(w / 2))
  .force("y", d3.forceY(h / 2))
  .force("collide", d3.forceCollide(function(d) {
    return d.size
  }))
  .stop();

for (var i = 0; i < 100; ++i) simulation.tick();

var nodes = svg.selectAll(null)
  .data(data.children)
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", function(d) {
    return d.size
  })
  .style("fill", function(_, i) {
    return color(i)
  })
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;

现在所有圈子都有10个大小:

&#13;
&#13;
var w = 500,
  h = 400;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var color = d3.scaleOrdinal(d3.schemeCategory10)

var data = {
  name: "root",
  children: [{
    label: 'RAD',
    size: 10,
    color: '#c99700'
  }, {
    label: 'BIL',
    size: 10,
    color: '#008ce6'
  }, {
    label: 'EEN',
    size: 10,
    color: '#007377'
  }, {
    label: 'INO',
    size: 10,
    color: '#b4975a'
  }, ]
};

var simulation = d3.forceSimulation(data.children)
  .force("x", d3.forceX(w / 2))
  .force("y", d3.forceY(h / 2))
  .force("collide", d3.forceCollide(function(d) {
    return d.size
  }))
  .stop();

for (var i = 0; i < 100; ++i) simulation.tick();

var nodes = svg.selectAll(null)
  .data(data.children)
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", function(d) {
    return d.size
  })
  .style("fill", function(_, i) {
    return color(i)
  })
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;

最后,让我们制作一个圆圈5000.你唯一能看到的就是将整个SVG作为一种颜色...但这就是你要求的:圆圈有一个半径5000像素。检查一下:

&#13;
&#13;
var w = 500,
  h = 400;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

var color = d3.scaleOrdinal(d3.schemeCategory10)

var data = {
  name: "root",
  children: [{
    label: 'RAD',
    size: 5000,
    color: '#c99700'
  }, {
    label: 'BIL',
    size: 100,
    color: '#008ce6'
  }, {
    label: 'EEN',
    size: 100,
    color: '#007377'
  }, {
    label: 'INO',
    size: 100,
    color: '#b4975a'
  }, ]
};

var simulation = d3.forceSimulation(data.children)
  .force("x", d3.forceX(w / 2))
  .force("y", d3.forceY(h / 2))
  .force("collide", d3.forceCollide(function(d) {
    return d.size
  }))
  .stop();

for (var i = 0; i < 100; ++i) simulation.tick();

var nodes = svg.selectAll(null)
  .data(data.children)
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .attr("r", function(d) {
    return d.size
  })
  .style("fill", function(_, i) {
    return color(i)
  })
&#13;
<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

制作属性&#39; r&#39;返回每个数据节点的大小,如下所示:

.attr('r', function (d) {
    return d.size;
})

我不确定您想要从您的尺寸中定义哪个圆圈属性,但您可以相应地进行修改。现在,半径设置为150,120,100

现在您的数据将更改圆的大小。您可以尝试使用此数据:

var data = {
    name: "root",
    children: [{
        label: 'RAD',
        size: 150,
        color: '#c99700'
    }, {
        label: 'BIL',
        size: 120,
        color: '#008ce6'
    }, {
        label: 'EEN',
        size: 100,
        color: '#007377'
    }]
};

请参阅codepen:https://codepen.io/andrewgi/pen/xWvNJe