我正在尝试使用静态大小圆圈值来实现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;
});
答案 0 :(得分:2)
实际上有一个方便的方法,名为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;
您实际上不想要圈组布局。圆包布局必须适合pack.size
数组指定区域内的所有圆圈。
因为你想设置圈子&#39;确定自己的尺寸,你希望D3只关注放置,我想到的最明显的选择是使用力模拟。
在此提议的解决方案中,我们使用forceX
和forceY
将焦点设置为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:
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;
现在让我们将3个圆圈的大小减少到20:
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;
现在所有圈子都有10个大小:
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;
最后,让我们制作一个圆圈5000.你唯一能看到的就是将整个SVG作为一种颜色...但这就是你要求的:圆圈有一个半径5000像素。检查一下:
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;
答案 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