2

The following is the code of rectangle with text within.

enter image description here

The problem is that it can't seem to align. How to make them align more easily?

Here's the code I use:

I know I can adjust the x and y for rectangle and text, but a more organized way to make them align is probably to have one g for each rectangle and related text, and adjust their positions within the g? How to achieve that?

<!DOCTYPE html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.8/d3.min.js" type="text/JavaScript"></script>
<!--script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.js" type="text/JavaScript"></script-->
<style>
    rect {
        stroke: #9A8B7A;
        stroke-width: 1px;
        fill: #CF7D1C;
        opacity:
    }
</style>
<body></body>
<script>
    var dataset = [[1,3,3,5,6,7],[3,5,8,3,2,6],[9,0,6,3,6,3],[3,4,4,5,6,8],[3,4,5,2,1,8]];

    var svg = d3.select("body")
            .append("svg")
            .attr("width", 500)
            .attr("height", 500);
    var local = d3.local();


    svg.append("g")
            .selectAll("g")
            .data(dataset)
            .enter()
            .append("g")
            .selectAll("text")
            .data(function(d, i) {

                local.set(this, i)
                return d;
            })
            .enter()
            .append("text")
            .text(function(d, i, j) {
                return d;
            })
            .attr("x", function(d, i, j) {
                return (i * 20) + 40;
            })
            .attr("y", function(d) {
                return (local.get(this) * 20) + 40;
            })
            .attr("font-family", "sans-serif")
            .attr("font-size", "20px");




    svg.append("g")
            .selectAll("g")
            .data(dataset)//use top-level data to join g
            .enter()
            .append("g")
            .selectAll("rect")
            .data(function(d, i) {//for each <g>, use the second-level data (return d) to join rect
                console.log(this);
                local.set(this, i);//this is the <g> parent
                return d;
            })
            .enter()
            .append("rect")

            .attr("x", function(d, i, j) {
                return (i * 20) + 40;

            })
            .attr("y", function(d) {
                return (local.get(this) * 20) + 40;
            })
            .attr("width",20)
            .attr("height",20)
            .attr("fill-opacity",0.1)




</script>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
william007
  • 17,375
  • 25
  • 118
  • 194

1 Answers1

3

An easy solution is just setting the dominant-baseline. This is a nice image with the possible values:

enter image description here

Source: http://bl.ocks.org/eweitnauer/7325338

So, in your case, just do:

.attr("dominant-baseline", "text-before-edge")

Here is your code with that change:

var dataset = [
  [1, 3, 3, 5, 6, 7],
  [3, 5, 8, 3, 2, 6],
  [9, 0, 6, 3, 6, 3],
  [3, 4, 4, 5, 6, 8],
  [3, 4, 5, 2, 1, 8]
];

var svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 500);
var local = d3.local();

svg.append("g")
  .selectAll("g")
  .data(dataset) //use top-level data to join g
  .enter()
  .append("g")
  .selectAll("rect")
  .data(function(d, i) {
    local.set(this, i); //this is the <g> parent
    return d;
  })
  .enter()
  .append("rect")
  .attr("x", function(d, i, j) {
    return (i * 20) + 40;

  })
  .attr("y", function(d) {
    return (local.get(this) * 20) + 40;
  })
  .attr("width", 20)
  .attr("height", 20)
  .attr("fill", "tan")
  .attr("stroke", "dimgray")
  .attr("fill-opacity", 0.4);
  
  svg.append("g")
  .selectAll("g")
  .data(dataset)
  .enter()
  .append("g")
  .selectAll("text")
  .data(function(d, i) {
    local.set(this, i)
    return d;
  })
  .enter()
  .append("text")
  .text(function(d, i, j) {
    return d;
  })
  .attr("x", function(d, i, j) {
    return (i * 20) + 40;
  })
  .attr("y", function(d) {
    return (local.get(this) * 20) + 40;
  })
  .attr("dominant-baseline", "text-before-edge")
  .attr("font-family", "sans-serif")
  .attr("font-size", "20px");
<script src="https://d3js.org/d3.v4.min.js"></script>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • Thanks! I have another following up question: https://stackoverflow.com/questions/46631532/placing-text-at-center-of-rectangle Could help look into it? – william007 Oct 08 '17 at 13:18