{
const svg = d3.create('svg')
.attr("viewBox", [0, 0, chart_dimensions.width, chart_dimensions.height]);
mergeGeoJsonAndBudgetData()
const clippedWidth = chart_dimensions.width - chart_dimensions.margin * 2;
const clippedHeight = chart_dimensions.height - chart_dimensions.margin * 2;
const legend_title = svg.append("g")
legend_title.attr("class", "legend")
.style('font-size', 12)
.style('font-family', 'sans-serif')
.attr("transform", `translate(${centerScale(7)},50)`)
.append("text")
.attr("font-weight", "bold")
.text("Income Class Code")
const legend_group = svg.append("g")
legend_group.attr("transform", `translate(${centerScale(7)},70)`)
.call(legend)
const geoMercator = d3
.geoMercator()
.center([199, 36])
.fitSize([clippedWidth, clippedHeight], geoJson);
const pathGen = d3.geoPath(geoMercator);
// initialize zoom
const zoom = d3.zoom()
.scaleExtent([1, 8])
.on('zoom', zoomed);
// initialize stage
// stage is basically just a group appended to the main svg
const stage = svg
.append('g')
.attr('transform', `translate(${chart_dimensions.margin},${chart_dimensions.margin})`);
// initialize Hover text on the upper left
const textX = 10;
const textY = 10;
const infoText = stage
.append('g')
.attr('transform', `translate(${textX},${textY})`)
.append('text')
.style("font", "20px sans-serif");
infoText.text('no data');
// setup onMouseHover, onMouseMove, onMouseLeave on the polugons
const onMouseHover = d => {
let income_class_text = d.properties.income_class;
let income_group_text = d.properties.income_group;
if (d.properties.income_class == undefined)
{
income_class_text = `<span style="color:red">No information available</span>`
income_group_text = `<span style="color:red">No information available</span>`
}
stage
.selectAll('.geopath')
.filter(td => td.properties.ADM2_EN === d.properties.ADM2_EN)
.attr('fill', 'yellow');
infoText.text(d.properties.ADM2_EN);
tooltip.html(`<div> <strong>Province: </strong>${d.properties.ADM2_EN}</div>
<div> <strong>Region: </strong>${d.properties.ADM1_EN}</div>
<div> <strong>Income Code: </strong>${income_class_text}</div>
<div> <strong>Income Class: </strong>${income_group_text}</div>`)
.style('visibility', 'visible');
};
const onMouseMove = d => {
tooltip
.style('top', d3.event.pageY - 10 + 'px')
.style('left', d3.event.pageX + 10 + 'px');
}
const onMouseLeave = d => {
stage
.selectAll('.geopath')
.filter(td => td.properties.ADM2_EN === d.properties.ADM2_EN)
.attr('fill', function(td) {
if (typeof td.properties.income_class === "number"){
return colorScale(td.properties.income_class)
}
else{
return "white"
}});
infoText.text('Hover on a province');
tooltip.html(``).style('visibility', 'hidden');
};
// initialize tEnter (polygons that composes the map)
// initialize tUpdate, tExit (optional)
const tEnter = enter =>
enter
.append('path')
.attr('d', pathGen)
.attr('stroke', 'purple')
.attr('fill', function(td) {
if (typeof td.properties.income_class === "number"){
return colorScale(td.properties.income_class)
}
else{
return "white"
}})
.classed('geopath', true)
.on('mouseenter', onMouseHover)
.on('mousemove', onMouseMove)
.on('mouseleave', onMouseLeave);
const tUpdate = null;
const tExit = null;
// setup stage
stage
.selectAll('.geopath')
.data(geoJson.features)
.join(tEnter, tUpdate, tExit);
// call zoom
svg.call(zoom);
// zoomed functio nfor zoom
function zoomed() {
stage
.selectAll('path') // To prevent stroke width from scaling
.attr('transform', d3.event.transform);
}
return svg.node();
}