Skip to content

Instantly share code, notes, and snippets.

@vicapow
Created March 15, 2015 19:14
Show Gist options
  • Save vicapow/a5586b51071a4bff4e65 to your computer and use it in GitHub Desktop.
Save vicapow/a5586b51071a4bff4e65 to your computer and use it in GitHub Desktop.
masonic demo
// 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);
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<script src="http://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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment