如何在 D3.js 中施加气泡的重力
How to force the gravity of bubbles in D3.js
在下面的代码中,我需要让数值最高的气泡漂浮在屏幕的左边,但是我对D3.js了解不深,找不到办法这样做。
我的代码
<script type="text/javascript">
dataset = {
"children": [{"Name":"Olives","Count":10},
{"Name":"Tea","Count":8},
{"Name":"Mashed Potatoes","Count":6},
{"Name":"Boiled Potatoes","Count":5},
{"Name":"Milk","Count":4},
{"Name":"Chicken Salad","Count":4},
{"Name":"Vanilla Ice Cream","Count":2},
{"Name":"Cocoa","Count":7}];
var diameter = 600;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var bubble = d3.pack(dataset)
.size([diameter, diameter])
.padding(1.5);
var svg = d3.select("body")
.append("svg")
.attr("width", diameter)
.attr("height", diameter)
.attr("class", "bubble");
var nodes = d3.hierarchy(dataset)
.sum(function(d) { return d.Count; });
var node = svg.selectAll(".node")
.data(bubble(nodes).descendants())
.enter()
.filter(function(d){
return !d.children
})
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title")
.text(function(d) {
return d.Name + ": " + d.Count;
});
node.append("circle")
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d,i) {
return color(i);
});
node.append("text")
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.Name.substring(0, d.r / 3);
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d){
return d.r/5;
})
.attr("fill", "white");
node.append("text")
.attr("dy", "1.3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.Count;
})
.attr("font-family", "Gill Sans", "Gill Sans MT")
.attr("font-size", function(d){
return d.r/5;
})
.attr("fill", "white");
d3.select(self.frameElement)
.style("height", diameter + "px");
</script>
代码产生这个结果
我需要数值最高的气泡在左边,如下图。
我可以根据需要使用什么 属性 或 D3.js 的功能来控制气泡的严重程度?
谢谢!
d3.pack 中没有专门用于此的功能。 d3.force 允许您根据数据的值指定 x 和 y 位置,并可以实现您要查找的结果。
力模拟有一个基于数据计数的 .x 和 .y 函数,然后为了避免重叠,.collide 函数根据圆的半径调整圆的位置(加上 3px 的小填充) .
var simulation = d3.forceSimulation(nodes)
.force("forceX", d3.forceX().strength(.051).x(d => xScale(d.Count)))
.force("forceY", d3.forceY().strength(.051).y(d => yScale(d.Count)))
.force('collision', d3.forceCollide().radius(d => rScale(d.Count) + 3))
dataset = {
"children": [{"Name":"Olives","Count":10},
{"Name":"Tea","Count":8},
{"Name":"Mashed Potatoes","Count":6},
{"Name":"Boiled Potatoes","Count":5},
{"Name":"Milk","Count":4},
{"Name":"Chicken Salad","Count":4},
{"Name":"Vanilla Ice Cream","Count":2},
{"Name":"Cocoa","Count":7}]
}
let nodes = dataset.children
var width = 600;
var height = 600;
var margin = 50
var color = d3.scaleOrdinal(d3.schemeCategory20);
let extentCount = d3.extent(nodes, d => d.Count)
let maxRadius = 100
let yScale = d3.scaleLinear()
.domain(extentCount)
.range([height - maxRadius, maxRadius])
let xScale = d3.scaleLinear()
.domain(extentCount)
.range([(width - maxRadius), maxRadius])
let rScale = d3.scaleSqrt()
.domain(extentCount)
.range([5, maxRadius])
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin + margin)
.attr("height", height + margin + margin)
.attr("class", "bubble");
var g = svg.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")")
var simulation = d3.forceSimulation(nodes)
.force("forceX", d3.forceX().strength(.051).x(d => xScale(d.Count)))
.force("forceY", d3.forceY().strength(.051).y(d => yScale(d.Count)))
.force('collision', d3.forceCollide().radius(d => rScale(d.Count) + 3))
.on("tick", function(d){
node
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; })
})
.stop()
for (var i = 0; i < 120; i++) {
simulation.tick()
}
var node = g.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title")
.text(function(d) {
return d.Name + ": " + d.Count;
});
node.append("circle")
.attr("r", d => rScale(d.Count))
.style("fill", function(d,i) {
return color(i);
});
node.append("text")
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.Name.substring(0, rScale(d.Count) / 3);
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d){
return rScale(d.Count)/5;
})
.attr("fill", "white");
node.append("text")
.attr("dy", "1.3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.Count;
})
.attr("font-family", "Gill Sans", "Gill Sans MT")
.attr("font-size", function(d){
return d.r/5;
})
.attr("fill", "white");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
在下面的代码中,我需要让数值最高的气泡漂浮在屏幕的左边,但是我对D3.js了解不深,找不到办法这样做。
我的代码
<script type="text/javascript">
dataset = {
"children": [{"Name":"Olives","Count":10},
{"Name":"Tea","Count":8},
{"Name":"Mashed Potatoes","Count":6},
{"Name":"Boiled Potatoes","Count":5},
{"Name":"Milk","Count":4},
{"Name":"Chicken Salad","Count":4},
{"Name":"Vanilla Ice Cream","Count":2},
{"Name":"Cocoa","Count":7}];
var diameter = 600;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var bubble = d3.pack(dataset)
.size([diameter, diameter])
.padding(1.5);
var svg = d3.select("body")
.append("svg")
.attr("width", diameter)
.attr("height", diameter)
.attr("class", "bubble");
var nodes = d3.hierarchy(dataset)
.sum(function(d) { return d.Count; });
var node = svg.selectAll(".node")
.data(bubble(nodes).descendants())
.enter()
.filter(function(d){
return !d.children
})
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title")
.text(function(d) {
return d.Name + ": " + d.Count;
});
node.append("circle")
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d,i) {
return color(i);
});
node.append("text")
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.Name.substring(0, d.r / 3);
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d){
return d.r/5;
})
.attr("fill", "white");
node.append("text")
.attr("dy", "1.3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.Count;
})
.attr("font-family", "Gill Sans", "Gill Sans MT")
.attr("font-size", function(d){
return d.r/5;
})
.attr("fill", "white");
d3.select(self.frameElement)
.style("height", diameter + "px");
</script>
代码产生这个结果
我需要数值最高的气泡在左边,如下图。
我可以根据需要使用什么 属性 或 D3.js 的功能来控制气泡的严重程度? 谢谢!
d3.pack 中没有专门用于此的功能。 d3.force 允许您根据数据的值指定 x 和 y 位置,并可以实现您要查找的结果。
力模拟有一个基于数据计数的 .x 和 .y 函数,然后为了避免重叠,.collide 函数根据圆的半径调整圆的位置(加上 3px 的小填充) .
var simulation = d3.forceSimulation(nodes)
.force("forceX", d3.forceX().strength(.051).x(d => xScale(d.Count)))
.force("forceY", d3.forceY().strength(.051).y(d => yScale(d.Count)))
.force('collision', d3.forceCollide().radius(d => rScale(d.Count) + 3))
dataset = {
"children": [{"Name":"Olives","Count":10},
{"Name":"Tea","Count":8},
{"Name":"Mashed Potatoes","Count":6},
{"Name":"Boiled Potatoes","Count":5},
{"Name":"Milk","Count":4},
{"Name":"Chicken Salad","Count":4},
{"Name":"Vanilla Ice Cream","Count":2},
{"Name":"Cocoa","Count":7}]
}
let nodes = dataset.children
var width = 600;
var height = 600;
var margin = 50
var color = d3.scaleOrdinal(d3.schemeCategory20);
let extentCount = d3.extent(nodes, d => d.Count)
let maxRadius = 100
let yScale = d3.scaleLinear()
.domain(extentCount)
.range([height - maxRadius, maxRadius])
let xScale = d3.scaleLinear()
.domain(extentCount)
.range([(width - maxRadius), maxRadius])
let rScale = d3.scaleSqrt()
.domain(extentCount)
.range([5, maxRadius])
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin + margin)
.attr("height", height + margin + margin)
.attr("class", "bubble");
var g = svg.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")")
var simulation = d3.forceSimulation(nodes)
.force("forceX", d3.forceX().strength(.051).x(d => xScale(d.Count)))
.force("forceY", d3.forceY().strength(.051).y(d => yScale(d.Count)))
.force('collision', d3.forceCollide().radius(d => rScale(d.Count) + 3))
.on("tick", function(d){
node
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; })
})
.stop()
for (var i = 0; i < 120; i++) {
simulation.tick()
}
var node = g.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title")
.text(function(d) {
return d.Name + ": " + d.Count;
});
node.append("circle")
.attr("r", d => rScale(d.Count))
.style("fill", function(d,i) {
return color(i);
});
node.append("text")
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.Name.substring(0, rScale(d.Count) / 3);
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d){
return rScale(d.Count)/5;
})
.attr("fill", "white");
node.append("text")
.attr("dy", "1.3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.Count;
})
.attr("font-family", "Gill Sans", "Gill Sans MT")
.attr("font-size", function(d){
return d.r/5;
})
.attr("fill", "white");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>