Skip to content

Instantly share code, notes, and snippets.

@mforando
Last active May 13, 2020 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mforando/037b7a4cb8f85908b4f1e05daba32fe9 to your computer and use it in GitHub Desktop.
Save mforando/037b7a4cb8f85908b4f1e05daba32fe9 to your computer and use it in GitHub Desktop.
Fit Grid Items to Rect
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;top:0;right:0;bottom:0;left:0; }
#main{
width:500px;
vertical-align:top;
}
#mainsvg{
background:'rgb(240,240,240)';
}
</style>
</head>
<div id='main'>
<svg id='mainsvg' width="500" height="500">
<rect id='rect' transform='translate(50, 50)' width='380' height='300'></rect>
<svg>
</div>
<body>
<script>
// bisect
d3.range(30);
d3.range(30);
var width = 500;
var height = 700;
var desiredItems = 30;
// height/width
var desiredRatio = 4/3;
var colsarray = d3.range(desiredItems).map((d)=>{return d + 1;}).reverse();
var options = [];
// generate an dataset of all of the possible layouts up to an Nth column grid
colsarray.forEach((cols)=>{
// find number of rows required for n columns grid.
var rows = Math.ceil(desiredItems/cols);
var cellWidth = width/cols;
var cellHeight = cellWidth * desiredRatio
var gridHeight = cellHeight * rows;
var gridRatio = gridHeight/width;
// find aspect ratio of this layout.
var thisRatio = cols/rows;
// given number of columns/rows figure out which is the constraining value.
var sizePerRow = height/rows;
var sizePerCol = width/cols/desiredRatio;
// find cell width.
var colwidth = width/cols;
options.push({'columns': cols, 'rows': rows, 'gridaspect': gridRatio});
})
console.log(options);
function updateGrid(){
var rect = d3.select("#rect")
.node()
.getBoundingClientRect();
console.log(rect.height/rect.width);
var ratio = rect.height/rect.width;
var ratios = options.map((d)=>{return d.gridaspect});
var index = d3.bisectLeft(ratios, ratio);
// find the smallest aspect ratio to the actual screen ratio.
var valid = options.filter((d)=>{return d.gridaspect <= ratio});
var gridToUse = valid[valid.length-1];
var griddata = d3.cross(d3.range(gridToUse.rows), d3.range(gridToUse.columns));
var xScale = d3.scaleBand()
.range([0, rect.width])
.domain(d3.range(gridToUse.columns))
var yScale = d3.scaleBand()
.range([0, gridToUse.rows * xScale.bandwidth() * desiredRatio])
.domain(d3.range(gridToUse.rows))
console.log(gridToUse.rows);
d3.select("#mainsvg")
.selectAll('.gridrects')
.data(griddata)
.enter()
.append('rect')
.style('fill', 'red')
.style('opacity', .5)
.attr('transform', 'translate(50, 50)')
.style('stroke', 'white')
.attr('width', xScale.bandwidth())
.attr('height', yScale.bandwidth())
.attr('x', (d)=>{return xScale(d[1])})
.attr('y', (d)=>{return yScale(d[0])})
console.log(griddata);
}
updateGrid();
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment