Grid layout demo.
forked from herrstucki's block: Grid layout in v4
forked from basilesimon's block: Grid layout in v4
license: mit |
Grid layout demo.
forked from herrstucki's block: Grid layout in v4
forked from basilesimon's block: Grid layout in v4
(function() { | |
d3.grid = function() { | |
var mode = "equal", | |
layout = _distributeEqually, | |
x = d3.scaleOrdinal(), | |
y = d3.scaleOrdinal(), | |
size = [1, 1], | |
actualSize = [0, 0], | |
nodeSize = false, | |
bands = false, | |
padding = [0, 0], | |
cols, rows; | |
function grid(nodes) { | |
return layout(nodes); | |
} | |
function _distributeEqually(nodes) { | |
var i = -1, | |
n = nodes.length, | |
_cols = cols ? cols : 0, | |
_rows = rows ? rows : 0, | |
col, row; | |
if (_rows && !_cols) { | |
_cols = Math.ceil(n / _rows) | |
} else { | |
_cols || (_cols = Math.ceil(Math.sqrt(n))); | |
_rows || (_rows = Math.ceil(n / _cols)); | |
} | |
if (nodeSize) { | |
x.domain(d3.range(_cols)).range(d3.range(0, (size[0] + padding[0]) * _cols, size[0] + padding[0])); | |
y.domain(d3.range(_rows)).range(d3.range(0, (size[1] + padding[1]) * _rows, size[1] + padding[1])); | |
actualSize[0] = bands ? x(_cols - 1) + size[0] : x(_cols - 1); | |
actualSize[1] = bands ? y(_rows - 1) + size[1] : y(_rows - 1); | |
} else if (bands) { | |
var x = d3.scaleBand() | |
var y = d3.scaleBand() | |
x.domain(d3.range(_cols)).range([0, size[0]], padding[0], 0); | |
y.domain(d3.range(_rows)).range([0, size[1]], padding[1], 0); | |
actualSize[0] = x.bandwidth()-10; | |
actualSize[1] = y.bandwidth()-10; | |
} else { | |
var x = d3.scalePoint() | |
var y = d3.scalePoint() | |
x.domain(d3.range(_cols)).range([0, size[0]]); | |
y.domain(d3.range(_rows)).range([0, size[1]]); | |
actualSize[0] = x(1); | |
actualSize[1] = y(1); | |
} | |
while (++i < n) { | |
col = i % _cols; | |
row = Math.floor(i / _cols); | |
nodes[i].x = x(col); | |
nodes[i].y = y(row); | |
} | |
return nodes; | |
} | |
grid.size = function(value) { | |
if (!arguments.length) return nodeSize ? actualSize : size; | |
actualSize = [0, 0]; | |
nodeSize = (size = value) == null; | |
return grid; | |
} | |
grid.nodeSize = function(value) { | |
if (!arguments.length) return nodeSize ? size : actualSize; | |
actualSize = [0, 0]; | |
nodeSize = (size = value) != null; | |
return grid; | |
} | |
grid.rows = function(value) { | |
if (!arguments.length) return rows; | |
rows = value; | |
return grid; | |
} | |
grid.cols = function(value) { | |
if (!arguments.length) return cols; | |
cols = value; | |
return grid; | |
} | |
grid.bands = function() { | |
bands = true; | |
return grid; | |
} | |
grid.points = function() { | |
bands = false; | |
return grid; | |
} | |
grid.padding = function(value) { | |
if (!arguments.length) return padding; | |
padding = value; | |
return grid; | |
} | |
return grid; | |
}; | |
})(); |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: Helvetica; | |
font-size: 10px; | |
} | |
.point, .rect { | |
fill: #222; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v4.min.js"></script> | |
<script src="d3-grid.js"></script> | |
<script> | |
var points = []; | |
var rects = []; | |
var width = 960, | |
height = 500; | |
var pointGrid = d3.grid() | |
.points() | |
.size([360, 360]); | |
var rectGrid = d3.grid() | |
.bands() | |
.size([360, 360]) | |
.padding([1, 1]); | |
var svg = d3.select("body").append("svg") | |
.attr('width', width) | |
.attr('height', height) | |
.append("g") | |
.attr("transform", "translate(70,70)"); | |
var tick = setInterval(push, 500); | |
function update() { | |
var point = svg.selectAll(".point") | |
.data(pointGrid(points)); | |
point.enter().append("circle") | |
.attr("class", "point") | |
.attr("r", 1e-6) | |
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | |
point.transition() | |
.attr("r", 5) | |
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | |
point.exit().transition() | |
.attr("r", 1e-6) | |
.remove(); | |
var rect = svg.selectAll(".rect") | |
.data(rectGrid(rects)); | |
rect.enter().append("rect") | |
.attr("class", "rect") | |
.attr("width", rectGrid.nodeSize()[0]) | |
.attr("height", rectGrid.nodeSize()[1]) | |
.attr("transform", function(d) { return "translate(" + (d.x + 460)+ "," + d.y + ")"; }) | |
.style("opacity", 1e-6); | |
rect.transition() | |
.attr("width", rectGrid.nodeSize()[0]) | |
.attr("height", rectGrid.nodeSize()[1]) | |
.attr("transform", function(d) { return "translate(" + (d.x + 460)+ "," + d.y + ")"; }) | |
.style("opacity", 1); | |
rect.exit().transition() | |
.style("opacity", 1e-6) | |
.remove(); | |
} | |
function push() { | |
points.push({}); | |
rects.push({}); | |
update(); | |
if (points.length > 15) { | |
clearInterval(tick); | |
tick = setInterval(pop, 500); | |
} | |
} | |
function pop() { | |
points.pop(); | |
rects.pop(); | |
update(); | |
if (points.length < 2) { | |
clearInterval(tick); | |
tick = setInterval(push, 500); | |
} | |
} | |
</script> |