简体   繁体   中英

D3 bubble chart / force layout forceAttraction

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 dx; }) .attr("cy", function(d) { return dy; }) }); // What happens when a circle is dragged? function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(.03).restart(); d.fx = dx; d.fy = dy; } 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?

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 dx; }) .attr("cy", function(d) { return dy; }) }); // What happens when a circle is dragged? function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(.03).restart(); d.fx = dx; d.fy = dy; } 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM