function hexgrid_transition(config = {}, svg) {
let {width, height, rows, columns, rotate=false, scale= () => 1, fill, stroke, stroke_width} = config;
svg = svg? d3.select(svg): d3.create("svg")
svg.attr("width", width)
.attr("height", height)
function add(x,y) { return x.map( (d,i) => d+y[i] ) };
function div(x,y) { return x.map( (d,i) => d/y[i] ) };
function mul(x,y) { return x.map( (d,i) => d*y[i] ) };
function r(x) { return rotate?[x[1],x[0]]:x }
const radius = d3.min(div([width,height],mul(add([columns,rows],r([0.5,1/3])),r([sqrt3,1.5]))));
let centers = [];
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
centers.push( {
x: (rotate? (j+2/3)*1.5: (i%2? j+1: j+0.5)*sqrt3) *radius,
y: (rotate? (j%2? i+1: i+0.5)*sqrt3 :(i+2/3)*1.5) *radius
} );
}
}
svg.selectAll("path")
.data(centers)
.join("path")
.transition()
.attr("transform", d => `translate(${d.x},${d.y}) scale(${scale(d,i)}) ${rotate? "rotate(30)": ""}` )
.attr("d", (d,i) => `m${hex.map((p) => p.map((d) => d*radius).join(',')).join('l')}z` )
.attr("fill", fill)
.attr("stroke", stroke)
.attr("stroke-width", stroke_width)
return svg.node()
}