datafunk
datafunk

Reputation: 636

removing magic number in drawing rows of svg rect

I have an SVG element and am drawing rectangles of set size. I calculate max columns max_cols and required rows min_rows to match dataset. When I reach the end of the SVG canvas I start a new row, however my algorhytm to calculate the y coordinate uses magic numbers. How can I get rid of it? Below are the relevant blocks of my (D3.js) code:

var rw = 17; // rect width
var rh = 17; // rect height
var rm = 2;  // rect margin
var min_rows = Math.ceil(c * (rw + rm) / w );
var max_cols = ( Math.ceil(w / (rh + rm)) ) - 2;

...

.attr('x', function(d, i) {
    var rem = i % max_cols;
    if (i < max_cols){
        return i * (rw + rm);                    
    } else {
        return rem * (rw + rm);
    }
})
.attr('y', function(d, i) {
    if (i < max_cols){
        return rh + rm;                    
    } else if (i < max_cols * 2) {
        return 2 * (rh + rm);
    } else if (i < max_cols * 3){
        return 3 * (rh + rm);
    } else {
        return 4 * (rh + rm);
    }
})

...

and in case this helps, here's the visual outcome: rendered rectangles on svg

Upvotes: 0

Views: 110

Answers (1)

Ben Lyall
Ben Lyall

Reputation: 1976

I'd do it something like this:

        var width = 323,
          height = 400,
          rw = 17,
          rh = 17,
          rm = 2,
          num_cols = parseInt(width / (rw + rm)),

          data = [
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#880", "#880", "#880",
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#008", "#008", "#008", "#008",
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#880", "#880", "#880",
            "#800", "#800", "#800", "#800", "#800", "#800", "#800",
            "#800", "#800", "#800", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#008", "#008", "#008",
            "#008", "#008", "#008", "#008", "#880", "#880", "#880",
            "#888", "#888", "#080", "#880", "#880", "#880", "#880",
            "#880", "#880", "#880", "#880", "#880",
          ];

        var svg = d3.select("#vis").append("svg")
          .attr("width", width)
          .attr("height", height);

        var rects = d3.select("svg").selectAll("rect")
          .data(data)
          .enter().append("rect")
          .attr("width", rw)
          .attr("height", rh)
          .attr("x", function(d, i) {
            return (i % num_cols) * (rw + rm);
          }).attr("y", function(d, i) {
            return parseInt(i / num_cols) * (rh + rm);
          }).style("fill", function(d) {
            return d;
          });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="vis"></div>

Basically, the y position, is just parseInt(i * (rh + rm) / num_cols) and the x position is just (i % num_cols) * (rw + rm);

Upvotes: 3

Related Questions