The article introduces how to use d3js showing the map of New Zealand regional council boundaries.
You can get the geometry data of NZ regional council from the NZ official website: https://datafinder.stats.govt.nz/layer/92197-meshblock-2018-generalised, remember to download the WGS84(EPSG:4326) projection format.
I downloaded the original data from the above URL and converted it to the Topo-JSON type as below.
Move the mouse to the map to get the regional councils’ basic info:
The source code is here:
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<div id="map-nz-regional-council"></div>
<script>
window.addEventListener('load', async () => {
await init_map();
})
async function init_map(){
let width = 960
, height = 960
, centered;
const file_name_topojson = '/wp-content/uploads/2021/03/regional_council_2018_generalised.topojson.json';
const topo_json = await d3.json(file_name_topojson);
const zoom = d3.zoom()
.scaleExtent([1, 4])
.on('zoom', zoomed);
function zoomed(event) {
const {transform} = event;
g.attr("transform", transform);
g.attr("stroke-width", 1 / transform.k);
}
const projection =
d3.geoMercator()
.scale(2000)
.center([176, -38]);
const path = d3.geoPath(projection);
const svg = d3.select('#map-nz-regional-council').append('svg')
.attr('width', width)
.attr('height', height)
.attr('fill', '#fff');
svg.append('rect')
.attr('class', 'background')
.attr('width', width)
.attr('height', height)
.on('click', clicked);
svg.call(zoom);
const g = svg.append('g');
const textLayer = g.append('g');
const mapLayer = g.append('g')
.classed('map-layer', true);
// const features = geo_json.features;
// Draw each provinces as a path
mapLayer.selectAll('path')
// .data(geo_json.features)
.data(topojson.feature(topo_json, topo_json.objects['regional_council_2018_generalised']).features)
.enter()
.append('path')
.attr('d', path)
.attr('vector-effect', 'non-scaling-stroke')
.style('stroke', '#000000')
// .style('fill', fillFn)
.on('mouseover', mouseover)
.on('mouseout', mouseout)
.on('click', clicked)
;
function clicked(d){
const pointer = d3.pointer(d);
const res = projection(pointer);
showInfo(d3.select(this).data());
}
function showInfo(data){
textLayer.selectAll('text').remove();
if(data && data[0]){
Object.keys(data[0]['properties']).map((k, i) => {
textLayer.append('text')
.attr('x', 0)
.attr('y', i * 14)
.attr('dy', '1.2em')
.style('fill', '#000')
.text( k + " => " + data[0]['properties'][k] );
});
}
}
function mouseover(d){
// Highlight hovered province
d3.select(this).style('fill', 'orange');
showInfo(d3.select(this).data());
}
function mouseout(d){
// Reset province color
mapLayer.selectAll('path')
.style('fill', function(d){return centered && d===centered ? '#D5708B' : '#ffffff';});
}
}
</script>