D3: How to set text inside a circle

Viewed 538

I'm newbie with D3.js and I'm trying to put a text inside a circle but I am only able to do it with one of them and not with all the circles.

You can find all the code in this snipet

Edit ORTG-DRTG-Scatterplot

And the function where I create the circles and I try to put the text inside of is "setPointsToCanvas"

  setPointsToCanvas(canvas, data, scales, x_label, y_label, lang) {
    canvas
      .selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("class", "dot")
      .attr("r", 20) //Radius size, could map to another dimension
      .attr("cx", function(d) {
        return scales.xScale(parseFloat(d.value_x));
      }) //x position
      .attr("cy", function(d) {
        return scales.yScale(parseFloat(d.value_y));
      }) //y position
      .style("fill", "#FFC107")
      .on("mouseover", tipMouseOver)
      .on("mouseout", tipMouseOut);

//Ad label for each circle
canvas
  .data(data)
  //.enter()
  .append("text")
  .attr("x", function(d) {
    return scales.xScale(parseFloat(d.value_x));
  })
  .attr("y", function(d) {
    return scales.yScale(parseFloat(d.value_y) - 0.9);
  })
  .text(function(d) {
    return d.name.substring(0, 3);
  })
  .style("text-anchor", "middle")
  .style("font-weight", "bold")
  .style("font-size", "10pt")
  .style("fill", "#344761");

let tooltip = d3
  //.select("#" + this.props.idContainer)
  .select("body")
  .append("div")
  .attr("class", "tooltip-player")
  .style("opacity", 0);

/**
 * We define this function inside of setPointsToCanvas to get access to canvas, data, scales and tooltip
 * @param {*} d
 * @param {*} iter
 */
function tipMouseOver(d, iter) {
  let players = data.filter(p => {
    if (p.value_x === d.value_x && p.value_y === d.value_y) {
      return p;
    }
  });
  let html = "";
  for (let i = 0; i < players.length; i++) {
    let text_x =
      lang === "es"
        ? String(parseFloat(players[i].value_x).toFixed(2)).replace(
            ".",
            ","
          )
        : parseFloat(players[i].value_x).toFixed(2);
    let text_y =
      lang === "es"
        ? String(parseFloat(players[i].value_y).toFixed(2)).replace(
            ".",
            ","
          )
        : parseFloat(players[i].value_y).toFixed(2);
    if (i > 0) html += "<hr>";
    html +=
      players[i].name +
      "<br><b>" +
      x_label +
      ": </b>" +
      text_x +
      "%<br/>" +
      "<b>" +
      y_label +
      ": </b>" +
      text_y +
      "%";
  }
  tooltip
    .html(html)
    .style("left", d3.event.pageX + 15 + "px")
    .style("top", d3.event.pageY - 28 + "px")
    .transition()
    .duration(200) // ms
    .style("opacity", 0.9); // started as 0!

  // Use D3 to select element, change color and size
  d3.select(this)
    //.attr("r", 10)
    .style("cursor", "pointer");
}

/**
 * We create this function inside of setPointsToCanvas to get access to tooltip
 */
function tipMouseOut() {
  tooltip
    .transition()
    .duration(500) // ms
    .style("opacity", 0); // don't care about position!
  //d3.select(this).attr("r", 5);
}
  }

And here you can see how I'm only able to get one text inside of one circle and not the text inside all of them.

enter image description here

What am I doing wrong?

1 Answers

Following the advice of @Pablo EM and thanks to @Andrew Reid for your appreciated help I publish the solution to my problem.

How @Andrew Reid said if I have problems with selectAll("text") I have to change it for another text grouper. How I had it, I changed by selectAll("textCircle") and everything works fine to me.

This is the code which writes the text inside each circle. This piede of code you can find it inside of "setPointsToCanvas" method.

//Ad label for each circle
canvas
  .selectAll("textCircle")
  .data(data)
  .enter()
  .append("text")
  .attr("x", function(d) {
    return scales.xScale(parseFloat(d.value_x));
  })
  .attr("y", function(d) {
    return scales.yScale(parseFloat(d.value_y) - 0.9);
  })
  .text(function(d) {
    return d.name.substring(0, 3);
  })
  .style("text-anchor", "middle")
  .style("font-weight", "bold")
  .style("font-size", "10pt")
  .style("fill", "#344761");

Now, here you've got an image of the final result:

enter image description here

If you access to the code through CodeSandBox posted before you can access to all the code and check how it works perfectly.

Related