0

I'd like to add a neighborhood name to each of the neighborhoods in my d3 map.

I used the centroid() function in this code.

var mapLabel = svg.selectAll("text")
    .data(json)
    .enter()
    .append("text")
    .text(function (d) {
        return d.properties.nhood;
    })
    .attr('transform', function (d) {
        return 'translate(' + path.centroid(d) + ')';
    })
    .attr('font-size', '6pt');

And it puts the names of each of the neighborhoods far from the center.

Images

Large version.

I tried with this code too.

function addText(p)
{
    var t = document.createElementNS("http://www.w3.org/2000/svg", "text");
    var b = p.getBBox();
    t.textContent = "a";
    t.setAttribute("transform", "translate(" + (b.x + b.width/2) + " " + (b.y + b.height/2) + ")");
    t.setAttribute("fill", "red");
    t.setAttribute("font-size", "14");
    p.parentNode.insertBefore(t, p.nextSibling);
}

var paths = document.querySelectorAll("path");
for (var p in paths)
{
    addText(paths[p])
}

The code worked to add text to the center of each SVG, but I don't know how to get it to add custom text for each neighborhood. Instead, I get "a" forty-one times.

I was also trying around with getBBox(). I couldn't access the function, I ran into the getBBox() is not a function error.

This is the section of code that creates the map.

var projection = d3.geoIdentity()
    .reflectY(true)
    .fitSize([w, h], jsonClone)

var pathFlipped = d3.geoPath()
    .projection(projection);

const mapSelection = svg.selectAll("path")
    .data(json)

mapSelection
    .enter()
    .append("path")
    .attr("d", pathFlipped)
    .style("fill", "lightgrey")

var mapLabel = svg.selectAll("text")
    .data(json)
    .enter()
    .append("text")
    .text(function (d) {
        return d.properties.nhood;
    })
    .attr('transform', function (d) {
        return 'translate(' + path.centroid(d) + ')';
    })
    .attr('font-size', '6pt');

This is a demo of the full map.

Wang Liang
  • 4,244
  • 6
  • 22
  • 45
Sebastian
  • 957
  • 3
  • 15
  • 27
  • how likely is it that your datasets (csv, json) vary during the dropbox selection? – rioV8 Feb 22 '19 at 09:47
  • each dropdown corresponds to a different column in the CSV. That said, I will only display the neighborhood names when the dropdown is set to "Default" – Sebastian Feb 22 '19 at 09:51
  • your json changes every dropdown change, so does the csv? – rioV8 Feb 22 '19 at 09:53
  • the csv stays static. the dropdown tells it to populate the map based on a different column in the csv. – Sebastian Feb 22 '19 at 09:55
  • then why load the static stuff each change? – rioV8 Feb 22 '19 at 11:58
  • You use a different path generator to place the text as compared to the features, try `pathFlipped.centroid(d)`, path uses a null projection, while pathFlipped scales and flips the coordinates to fit your map. Use the same path generator for feature and text. – Andrew Reid Feb 22 '19 at 21:40

2 Answers2

1

This is how I would find the center of a path. For this I'm using thePath.getBBox() as you intended. I've centered the text using dominant-baseline="middle" text-anchor="middle" I hope it helps.

let bb = thePath.getBBox()
let center = {}
center.x = bb.x + bb.width/2;
center.y = bb.y + bb.height/2;

theText.setAttributeNS(null,"x", center.x);
theText.setAttributeNS(null,"y", center.y);
svg{border:1px solid; width:90vh;font-size:10px;}
path{stroke:black; fill:none}
<svg viewBox="400 200 80 80">
<path id="thePath" d="M460.2747483221477,215.0904841802493L460.97974592521575,219.66323106423778L461.6808485139022,224.23208293384465L462.3585810162992,228.75419463087246L463.00515340364336,233.3464165867689L463.7257310642378,238.15286433365287L470.05902444870566,237.07005033557044L470.7990771812081,242.03229865771806L471.52744487056566,246.87380153403637L472.24802253116013,251.71530441035475L472.9919702780441,256.5451222435282L473.7437080536913,261.7994966442953L467.41430968360504,262.87452061361455L462.5377516778524,263.70415867689354L462.18330536912754,263.7314237775647L462.0976150527325,263.73531879194627L461.99244966442956,263.74700383509105L458.4518815915628,264.00017976989454L456.4264741131352,264.35852109300095L456.3641538830297,264.15208533077663L456.18108820709494,263.51330297219556L453.50131831255993,263.88722435282835L449.9490651965484,264.52600671140937L449.6024089165868,264.7636025886864L445.96446548418027,265.340064717162L445.71128954937683,265.78799137104505L445.2984180249281,265.4763902205177L442.0460810162991,266.0139022051773L441.76174496644296,266.4774089165868L441.3293983700863,266.13075263662506L438.14717162032605,266.6682646212848L437.8316754554171,267.15903643336526L437.4149089165868,266.8474352828379L434.16257190795784,267.4161073825503L433.8899209012464,267.86403403643334L433.51210450623205,267.5407478427612L430.4311481303931,268.0237296260786L430.0260666347076,268.47555129434323L429.61319511025886,268.1873202301054L426.0492569511026,268.8027325023969L425.7805009587728,269.2039189837008L425.4104745925216,268.8650527325024L425.0599232981783,268.91958293384465L424.8495925215724,269.3480345158197L424.42893096836053,269.04422339405556L422.15034755512943,269.231184084372L421.8815915627996,269.60900047938634L421.49988015340364,269.2662392138063L420.6040268456376,269.30908437200384L416.6934324065197,269.53110019175455L416.3623561840844,269.9517617449664L416.01959491850437,269.6362655800575L412.5335570469799,269.80764621284754L412.0388902205177,270.25167785234896L411.5052732502397,260.22201581975065L411.32610258868647,256.90735858101624L410.9833413231064,250.50784995206135L410.8080656759348,247.27498801534034L410.51204458293387,242.38674496644296L410.42245925215724,240.87547938638534L410.2510786193672,237.72441275167785L410.005692713327,233.13219079578136L409.75641179290506,228.48154362416102L409.67072147651004,226.3509707574305L411.38452780441037,226.32370565675933L417.3361097794823,224.71506471716202L423.64992809204216,223.00515340364336L429.82352588686484,221.3380872483221L435.5414069990412,219.79176653883025L442.2447267497603,217.98058485139023L448.2703139980825,216.34857382550337L448.4962248322148,217.12368168744L454.97752876318316,216.00581255992324Z"></path>
  
  
  
  <text id="theText" dominant-baseline="middle" text-anchor="middle" >Some text</text>
</svg>
enxaneta
  • 31,608
  • 5
  • 29
  • 42
1

You need to use the same projection for the text as used for the paths

.attr('transform', function(d) { return 'translate(' + pathFlipped.centroid(d) + ')'; })
rioV8
  • 24,506
  • 3
  • 32
  • 49