简体   繁体   中英

D3: How to set text inside a circle

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

编辑 ORTG-DRTG-散点图

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.

在此处输入图像描述

What am I doing wrong?

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:

在此处输入图像描述

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

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