Imi
Imi

Reputation: 549

How to arrange rectangles in rows in d3.js

I i have 100 rectangles that I want to arrange in 10x10. I have been able to arrange one row and column but I am stuck at arranging the other nine. Here is js fiddle:

code:

var ContainerWidth = document.querySelector('#mainContainer').offsetWidth;
   var rectWidth = ContainerWidth / 20
   console.log(ContainerWidth)
   var svgContainer = d3.select("#boxy")

   var rectangle = svgContainer.selectAll("rect")
     .data((function() {
       var arr = []
       for (var i = 1; i <= 100; i++) {
         arr.push(i)
       }
       return arr
     }()));

   var rectangle = rectangle.enter()
     .append("rect")
     .style("stroke", "black")
     .style("fill", "none")
     .attr("x", function(d, i) {
       if (i % 10 == 0) {
         return 5
       } else {
         return (i*45) + 3;
       }

     })
     .attr("y", function(d, i) {
       if (i % 10 == 0) {
         return i*4.2
       }

     })
     .attr("width", rectWidth)
     .attr("height", rectWidth);

the result should look something like this enter image description here

Upvotes: 1

Views: 1036

Answers (2)

icanc
icanc

Reputation: 3577

Just as an alternative method, here's how you could do it using "row" and "column" way. Uses a bit less math.

var svg = d3.select("svg");
var height = svg.attr("height");
var width = svg.attr("width");
var rectWidth = width / 20;

// Creates 10 rows.
var rows = svg.selectAll(".row")
  .data(d3.range(10))
  .enter().append("g")
  .attr("class", "row")
  .attr("transform", function(d, i) {
    return "translate(0," + (rectWidth * i) + ")";
  });

// For each row, create 10 rects.
var rects = rows.selectAll("rect")
  .data(d3.range(10))
  .enter().append("rect")
  .attr("x", function(d, i) {
    return rectWidth * i;
  })
  .attr("height", rectWidth)
  .attr("width", rectWidth);
rect {
  fill: black;
  stroke: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height="200" width="324"></svg>

JSFiddle version

Upvotes: 3

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

Firstly, you can simplify your data to just:

.data(d3.range(100));

To make the matrix with your rectangles, you can use:

 .attr("x", (d,i) => i%10 * 45)
 .attr("y", (d,i) => Math.floor(i/10)%10 * 45)

Here is a demo:

var ContainerWidth = document.querySelector('#mainContainer').offsetWidth;
var rectWidth = ContainerWidth / 20;
var svgContainer = d3.select("#boxy");

var rectangle = svgContainer.selectAll("rect")
    .data(d3.range(100));

rectangle.enter()
    .append("rect")
    .style("stroke", "black")
    .style("fill", "none")
    .attr("x", (d,i) => i%10 * 45)
    .attr("y", (d,i) => Math.floor(i/10)%10 * 45)
    .attr("width", rectWidth)
    .attr("height", rectWidth);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='mainContainer'>
  <svg id="boxy" viewBox="0 0 960 500" preserveAspectRatio="xMidYMid meet">
  </svg>
</div>

This other snippet show you the data bound to each rectangle:

var ContainerWidth = document.querySelector('#mainContainer').offsetWidth;
var rectWidth = ContainerWidth / 20;
var svgContainer = d3.select("#boxy");

var rectangle = svgContainer.selectAll("rect")
    .data(d3.range(100));

rectangle.enter()
    .append("rect")
    .style("stroke", "black")
    .style("fill", "none")
    .attr("x", (d,i) => i%10 * 45)
    .attr("y", (d,i) => Math.floor(i/10)%10 * 45)
    .attr("width", rectWidth)
    .attr("height", rectWidth);

rectangle.enter()
     .append("text")
     .attr("x", (d,i) => i%10 * 45 + 4)
     .attr("y", (d,i) => Math.floor(i/10)%10 * 45 + 16)
     .text((d,i)=>d);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='mainContainer'>
  <svg id="boxy" viewBox="0 0 960 500" preserveAspectRatio="xMidYMid meet">
  </svg>
</div>

Upvotes: 4

Related Questions