Reputation: 35
I am trying to create bubble chart.(I'm new to D3.js).
First, I tried to change the code by referring to this site(https://www.d3-graph-gallery.com/graph/circularpacking_drag.html) to make a bubble chart. the following code is original one.
// set the dimensions and margins of the graph
var width = 450
var height = 450
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", 450)
.attr("height", 450)
// create dummy data -> just one element per circle
var data = [{
"name": "A"
}, {
"name": "B"
}, {
"name": "C"
}, {
"name": "D"
}, {
"name": "E"
}, {
"name": "F"
}, {
"name": "G"
}, {
"name": "H"
}]
// Initialize the circle: all located at the center of the svg area
var node = svg.append("g")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("r", 25)
.attr("cx", width / 2)
.attr("cy", height / 2)
.style("fill", "#19d3a2")
.style("fill-opacity", 0.3)
.attr("stroke", "#b3a2c8")
.style("stroke-width", 4)
.call(d3.drag() // call specific function when circle is dragged
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// Features of the forces applied to the nodes:
var simulation = d3.forceSimulation()
.force("center", d3.forceCenter().x(width / 2).y(height / 2)) // Attraction to the center of the svg area
.force("charge", d3.forceManyBody().strength(1)) // Nodes are attracted one each other of value is > 0
.force("collide", d3.forceCollide().strength(.1).radius(30).iterations(1)) // Force that avoids circle overlapping
// Apply these forces to the nodes and update their positions.
// Once the force algorithm is happy with positions ('alpha' value is low enough), simulations will stop.
simulation
.nodes(data)
.on("tick", function(d) {
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
});
// What happens when a circle is dragged?
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(.03).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(.03);
d.fx = null;
d.fy = null;
}
<div id="my_dataviz"></div>
<script src="https://d3js.org/d3.v5.js"></script>
And in this chart, since there was no attraction function(attract to center), I tried to add the following code. (I referred to the following site https://blockbuilder.org/ericsoco/d2d49d95d2f75552ac64f0125440b35e)
.force('attract', d3.forceAttract()
.target([width/2, height/2])
.strength(0.01))
However, it is not working.And it changes like the following image.
Could anyone advice me why this happen?
Upvotes: 0
Views: 915
Reputation: 13129
The image you get from d3.forceAttract
not existing in d3 v5, as you can see from the console. You can use something like d3.forceRadial
, however to add an attraction towards the center:
// set the dimensions and margins of the graph
var width = 450
var height = 450
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width", 450)
.attr("height", 450)
// create dummy data -> just one element per circle
var data = [{
"name": "A"
}, {
"name": "B"
}, {
"name": "C"
}, {
"name": "D"
}, {
"name": "E"
}, {
"name": "F"
}, {
"name": "G"
}, {
"name": "H"
}]
// Initialize the circle: all located at the center of the svg area
var node = svg.append("g")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("r", 25)
.attr("cx", width / 2)
.attr("cy", height / 2)
.style("fill", "#19d3a2")
.style("fill-opacity", 0.3)
.attr("stroke", "#b3a2c8")
.style("stroke-width", 4)
.call(d3.drag() // call specific function when circle is dragged
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// Features of the forces applied to the nodes:
var simulation = d3.forceSimulation()
.force("center", d3.forceCenter().x(width / 2).y(height / 2)) // Attraction to the center of the svg area
.force("charge", d3.forceManyBody().strength(1)) // Nodes are attracted one each other of value is > 0
.force("collide", d3.forceCollide().strength(.1).radius(30).iterations(1)) // Force that avoids circle overlapping
.force('attract', d3.forceRadial(0, width / 2, height / 2).strength(0.05))
// Apply these forces to the nodes and update their positions.
// Once the force algorithm is happy with positions ('alpha' value is low enough), simulations will stop.
simulation
.nodes(data)
.on("tick", function(d) {
node
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
});
// What happens when a circle is dragged?
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(.03).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(.03);
d.fx = null;
d.fy = null;
}
<div id="my_dataviz"></div>
<script src="https://d3js.org/d3.v5.js"></script>
Upvotes: 1