block by vicapow a5586b51071a4bff4e65

masonic demo

Full Screen

index.html

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <style>
body {
  margin: 0;
}
    </style>
  </head>
  <body>
    <script src="//d3js.org/d3.v3.js" charset="utf-8"></script>
    <script src="d3-masonic.js" charset="utf-8"></script>
    <script>
'use strict';
var w = window.innerWidth, h = window.innerHeight
var s = 1
var duration = 500
var n = 6
var acc = function(d, prop) { return function accessor(d) { return d[prop] } }
var body = d3.select('body')
var svg = body.append('svg')
  .attr({width: w, height: h})
  .style('background-color', 'black')

var color = d3.scale.category20()

function randomSize(min, max, step) {
  return Math.round(min + Math.random() * (max - min)) * step
}

function genData() {
  return d3.range(n)
    .map(function(d, i) {
      var size = Math.pow(randomSize(2, 15, s), 2)
      return {
        width: size,
        height: size,
        id: i,
        masonic: null
      }
    })
}

var bricks = svg.selectAll('rect')
  .data(genData, function(d) { return d.id })
  .enter()
  .append('rect')
    .style('fill', function(d, i) { return color(i) })

var masonic = d3.masonic()
  .width(function(d) { return d.width })
  .height(function(d) { return d.height })
  .columnWidth(s)

function resize() {
  var outerWidth = body.property('offsetWidth')
  masonic.outerWidth(800).reset()
  bricks
    // .sort(function(a, b) { return b.width * b.height - a.width * a.height })
    .datum(function(d, i) {
      d.masonic = masonic(d)
      delete d.masonic.data
      return d
    })
    .transition()
    .ease('cubic-out')
    .duration(duration)
    .attr({
      x: function(d) { return d.masonic.x },
      y: function(d) { return 500 - d.masonic.y - d.masonic.height },
      width: function(d) { return d.masonic.width },
      height: function(d) { return d.masonic.height }
    })
}

resize()

setInterval(function() {
  bricks.data(genData, function(d) { return d.id })
  resize()
}, duration)

    </script>
  </body>
</html>

d3-masonic.js

// Checkout the project page at: https://github.com/shawnbot/masonic
(function(exports) {

  var VERSION = "0.1.0";

  d3.masonic = function() {
    var columnCount = 0,
        columnWidth = 200,
        outerWidth = 0,
        outerHeight = 0,
        columns = [],
        bricks = [],
        getWidth = function() { return this.offsetWidth; },
        getHeight = function() { return this.offsetHeight; },
        zero = d3.functor(0);

    function masonic(d, i) {
      if (columns.length === 0) {
        columns = d3.range(columnCount).map(zero);
      }

      var w = getWidth.apply(this, arguments) || 0,
          h = getHeight.apply(this, arguments) || 0,
          span = Math.ceil(w / columnWidth),
          brick = {
            width: w,
            height: h,
            data: d
          };

      span = brick.span = Math.min(span, columnCount);

      if (span === 1) {
        place(brick, columns);
      } else {
        var groupCount = columnCount + 1 - span,
            groupY = [],
            groupColY;
        for (var i = 0; i < groupCount; i++) {
          groupColY = columns.slice(i, i + span);
          groupY[i] = Math.max.apply(Math, groupColY);
        }

        place(brick, groupY);
      }

      return brick;
    }

    function place(brick, cols) {
      var minY = Math.min.apply(Math, cols),
          len = cols.length,
          shortest = 0;
      for (var i = 0; i < len; i++) {
        if (cols[i] === minY) {
          shortest = i;
          break;
        }
      }

      brick.column = shortest;
      brick.x = columnWidth * shortest;
      brick.y = minY;

      var setHeight = minY + brick.height,
          setSpan = columnCount + 1 - len;
      for (i = 0; i < setSpan; i++) {
        columns[shortest + i] = setHeight;
      }

      outerHeight = Math.max.apply(Math, columns);
      // XXX set outerWidth?
      outerWidth = Math.max(outerWidth, brick.x + brick.width);
    }

    // get/set the item width value (function)
    masonic.width = function(_) {
      if (!arguments.length) return getWidth;
      getWidth = d3.functor(_);
      return masonic;
    };

    // get/set the item height value (function)
    masonic.height = function(_) {
      if (!arguments.length) return getHeight;
      getHeight = d3.functor(_);
      return masonic;
    };

    // get/set column width
    masonic.columnWidth = function(_) {
      if (!arguments.length) return columnWidth;
      columnWidth = _;
      if (outerWidth === 0) {
        outerWidth = columnCount * columnWidth;
      }
      return masonic;
    };

    // get/set column count
    masonic.columnCount = function(_) {
      if (!arguments.length) return columnCount;
      columnCount = _;
      return masonic;
    };

    // get/set outer width
    // Note: the setter also sets columnWidth if columnCount > 0
    masonic.outerWidth = function(_) {
      if (!arguments.length) return outerWidth;
      outerWidth = _;
      if (columnWidth > 0) {
        columnCount = Math.floor(outerWidth / columnWidth);
      }
      return masonic;
    };

    // getter only
    masonic.outerHeight = function() {
      if (arguments.length) throw "outerHeight() is a getter only";
      return outerHeight;
    };

    masonic.reset = function() {
      bricks = [];
      columns = [];
      outerHeight = 0;
      return masonic;
    };

    return masonic.reset();
  };

  d3.masonic.version = VERSION;

})(this);