withZoom = {
const svgHeight = 0.25*width;
const top = htl.html`
<div class="wrapper">
<div class="info">
</div>
<svg viewBox="0 0 ${width} ${svgHeight}">
</svg>
</div>
`
const projection = d3.geoAlbersUsa();
const path = d3.geoPath().projection(projection)
projection.scale(1).translate([0,0]);
const b = path.bounds(districts);
const s = 0.95/Math.max((b[1][0]-b[0][0])/width, (b[1][1]-b[0][1])/svgHeight);
const t = [(width - s*(b[1][0]+b[0][0]))/2, (svgHeight - s*(b[1][1] + b[0][1]))/2];
projection.scale(s).translate(t);
d3.select(top).select('svg').append('g').selectAll('path').data(districts.features)
.enter()
.append('path')
.attr('d', path)
.attr('id', d => d.properties.district)
.classed("district", true);
d3.select(top).select('div.info').text('Click or touch a district for info');
function mapClick(event){
const coords = d3.pointer(event);
const longlat = projection.invert(coords);
d3.select(top).select('div.info').text(`Click or touch a district for info`);
districts.features.forEach(d => {
d3.select(top).select('#' + d.properties.district).classed('selected', false);
if (d3.geoContains(d,longlat)) {
d3.select(top).select('div.info').text(`${d.properties.district}`)
d3.select(top).select('#' + d.properties.district).classed('selected', true);
}
})
}
d3.select(top).select('svg')
.on('click', mapClick)
d3.select(top).select('svg').call(d3.zoom()
.extent([[0,0], [width, svgHeight]])
.scaleExtent([1,8])
.on("zoom", zoomed));
function zoomed({transform}) {
d3.select(top).select('svg').select('g').attr("transform", transform);
}
return top;
}