简体   繁体   中英

Add label/text to D3 circles?

I have the following CSV file:

city,population,latitude,longitude
New York; New York,8336697,40.712784,-74.005941
Los Angeles; California,3857799,34.052234,-118.243685
Houston; Texas,2160821,37.326159,-91.955988
San Antonio; Texas,1382951,29.419336,-98.478021
Austin; Texas,842592,32.552483,-98.370042
Charlotte; North Carolina,775202,35.227087,-80.843127
Dallas; Texas,1241162,32.191303,-96.878367
Phoenix; Arizona,1488750,33.448377,-112.074037
San Jose; California,982765,37.338208,-121.886329
Fort Worth; Texas,777992,32.755488,-97.330766

I would like to append the city value on top of circles I am rendering using D3. Here is the code that I am using to create these circles:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.counties {
    fill: #000;
        stroke: #fff;
        stroke-width: 0.25px;
}

.states {
        fill: none;
        stroke: #fff;
        stroke-linejoin: round;
}
</style>

<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
var width = 960,
        height = 500;

var projection = d3.geo.albersUsa()
                          .scale(1000)
                           .translate([width / 2, height / 2]);

var path = d3.geo.path()
                      .projection(projection);

var svg = d3.select("body").append("svg")
                 .attr("width", width)
                 .attr("height", height);
var layer = svg.append('g');
d3.json("us.json", function(error, us) {
    layer.append("g")
               .attr("class", "counties")
               .style("fill", "#fcfa86")
               .selectAll("path")
               .data(topojson.feature(us, us.objects.counties).features)
               .enter().append("path")
               .attr("d", path);

            svg.append("path")
               .datum(topojson.mesh(us, us.objects.states, function(a, b) { return  a !== b; }))
               .attr("class", "states")
               .style("stroke", "orange")
               .attr("d", path);

});

d3.csv("city_growth.csv", function(error, data) {
    svg.selectAll("circle")
        .data(data)
        .enter()
        .append("circle")
        .attr("cx", function(d) {return projection([d.longitude, d.latitude])[0];})
        .attr("cy", function(d) {return projection([d.longitude, d.latitude])[1];})
        .attr("r", function(d) {return Math.sqrt(d.population * 0.00004);})
        .style("opacity",".6")
        .style("fill", "red");

</script>
</body>

How can I create a reference to the city value and have it come up next to every single circle? I used the following code fragment to make this happen, but the labels are not coming up:

svg.selectAll("circle")
        .data(data)
        .enter()
        .append("text")
        .text(function(d) { return d.city; })
        .attr("x", function(d) {return projection([d.longitude, d.latitude])[0];})
        .attr("y", function(d) {return projection([d.longitude, d.latitude])[1];})
        .attr("font-size", "10px")
        .attr("color", "red");

What is the proper way to have the city names come up from the CSV file displayed at the top? Am I referring to the city column incorrectly? Any suggestion will be very helpful!

You cannot append text to circles with svg - but you can append both to a g ; this is your easiest and cleanest solution.

When appending the g, use the projection values to set a transform, this allows the center of the circle to be placed at [0,0] relative to the transform:

var g = svg.selectAll(null)
        .data(data)
        .enter()
        .append("g")
        .attr("transform", function(d) {
            return "translate(" + projection([d.longitude, d.latitude]) + ")" ;
        })

As the datum for each g holds the datum you want to display for each circle, you can now append circles and text easily as child elements:

g.append("circle")
  .attr("r", function(d) {return Math.sqrt(d.population * 0.00004);})
  .attr("fill","red")
  .attr("etc",...)

g.append("text")
  .text(function(d) { return d.city; })
  .attr("x"...)
  .attr("y"...)

Note that the circle doesn't need positioning anymore: cx and cy will default to zero - which is fine as we transformed the g 's coordinates. Also, using transform rather than both cx and cy is a little cleaner, especially when using projections (and by transforming the g , you don't need to use your projection to place the text either).

Lastly, you probably want to modify the x,y, and text-anchor properties of the text to suit your needs, but the default x,y of zero will place text starting at the center of the circle.

Append circles first, then text, so text appears above.

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