<!-- 
MIT License

Copyright (c) [2021] [Spruce Emmanuel]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this d3.js Example(s), to use without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Project, and to permit persons to whom the Project is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Project.
-->

<body id="svg_wrapper">
	<div class="btn-group-vertical" role="group" aria-label="..." id="float-button-group">
		<button class="btn-default" id="zoomIn"><svg class="svg-icon" viewBox="0 0 20 20">
				<title>Zoom In</title>
				<path fill="none" d="M13.388,9.624h-3.011v-3.01c0-0.208-0.168-0.377-0.376-0.377S9.624,6.405,9.624,6.613v3.01H6.613c-0.208,0-0.376,0.168-0.376,0.376s0.168,0.376,0.376,0.376h3.011v3.01c0,0.208,0.168,0.378,0.376,0.378s0.376-0.17,0.376-0.378v-3.01h3.011c0.207,0,0.377-0.168,0.377-0.376S13.595,9.624,13.388,9.624z M10,1.344c-4.781,0-8.656,3.875-8.656,8.656c0,4.781,3.875,8.656,8.656,8.656c4.781,0,8.656-3.875,8.656-8.656C18.656,5.219,14.781,1.344,10,1.344z M10,17.903c-4.365,0-7.904-3.538-7.904-7.903S5.635,2.096,10,2.096S17.903,5.635,17.903,10S14.365,17.903,10,17.903z"></path>
			</svg></button>
		<button class="btn-default" id="zoomOut"><svg class="svg-icon" viewBox="0 0 20 20">
				<title>Zoom Out</title>
				<path fill="none" d="M10,1.344c-4.781,0-8.656,3.875-8.656,8.656c0,4.781,3.875,8.656,8.656,8.656c4.781,0,8.656-3.875,8.656-8.656C18.656,5.219,14.781,1.344,10,1.344z M10,17.903c-4.365,0-7.904-3.538-7.904-7.903S5.635,2.096,10,2.096S17.903,5.635,17.903,10S14.365,17.903,10,17.903z M13.388,9.624H6.613c-0.208,0-0.376,0.168-0.376,0.376s0.168,0.376,0.376,0.376h6.775c0.207,0,0.377-0.168,0.377-0.376S13.595,9.624,13.388,9.624z"></path>
			</svg></button>
		<button class="btn-default" id="resetZoom"><svg class="svg-icon" viewBox="0 0 20 20">
				<title>Reset Zoom</title>
				<path d="M17.659,9.597h-1.224c-0.199-3.235-2.797-5.833-6.032-6.033V2.341c0-0.222-0.182-0.403-0.403-0.403S9.597,2.119,9.597,2.341v1.223c-3.235,0.2-5.833,2.798-6.033,6.033H2.341c-0.222,0-0.403,0.182-0.403,0.403s0.182,0.403,0.403,0.403h1.223c0.2,3.235,2.798,5.833,6.033,6.032v1.224c0,0.222,0.182,0.403,0.403,0.403s0.403-0.182,0.403-0.403v-1.224c3.235-0.199,5.833-2.797,6.032-6.032h1.224c0.222,0,0.403-0.182,0.403-0.403S17.881,9.597,17.659,9.597 M14.435,10.403h1.193c-0.198,2.791-2.434,5.026-5.225,5.225v-1.193c0-0.222-0.182-0.403-0.403-0.403s-0.403,0.182-0.403,0.403v1.193c-2.792-0.198-5.027-2.434-5.224-5.225h1.193c0.222,0,0.403-0.182,0.403-0.403S5.787,9.597,5.565,9.597H4.373C4.57,6.805,6.805,4.57,9.597,4.373v1.193c0,0.222,0.182,0.403,0.403,0.403s0.403-0.182,0.403-0.403V4.373c2.791,0.197,5.026,2.433,5.225,5.224h-1.193c-0.222,0-0.403,0.182-0.403,0.403S14.213,10.403,14.435,10.403"></path>
			</svg></button>

	</div>
	<svg id="d3_demo"></svg>
</body>
body {
	background: lightblue;
	position: relative;
	height: 100vh;
}
button {
	outline: 0px;
	border: 0px;
	cursor: pointer;
	outline-style: none;
}
path {
	stroke: white;
	stroke-width: 0.5px;
	fill: #ebebe0;
}

#float-button-group {
	position: absolute;
	left: 10px;
	top: 10px;
	opacity: 0.5;
	display: flex;
	flex-direction: column;
}

#float-button-group:hover {
	opacity: 1;
}
.svg-icon {
	width: 1.5em;
	height: 1.5em;
}
.svg-icon path,
.svg-icon polygon,
.svg-icon rect {
	fill: #333;
}
.btn-default {
	color: #333;
	background-color: #fff;
	border-color: #ccc;
	padding: 0.4rem;
}
.tooltip {
	position: absolute;
	text-align: center;
	padding: 12px;
	font: 15px sans-serif;
	background: lightsteelblue;
	border-radius: 11px;
	border-radius: 8px;
	pointer-events: none;
}
import * as d3 from "https://cdn.skypack.dev/d3";

// set the dimensions and margins of the graph
const margin = { top: 0, right: 0, bottom: 0, left: 0 },
	width = document.querySelector("body").clientWidth,
	height = document.querySelector("body").clientHeight;

const svg = d3.select("#d3_demo").attr("viewBox", [0, 0, width, height]);

let projection = d3.geoEquirectangular().center([0, 0]);
const pathGenerator = d3.geoPath().projection(projection);

// add title
svg
	.append("text")
	.attr("x", width / 1.4)
	.attr("y", `${height - 20}`)
	.style("font-size", "20x")
	.style("text-decoration", "underline")
	.text("Map of Nigeria and it's states ");

let g = svg.append("g");

Promise.all([
	d3.json(
		"https://raw.githubusercontent.com/iamspruce/intro-d3/main/data/nigeria_state_boundaries.geojson"
	),
	d3.json(
		"https://raw.githubusercontent.com/iamspruce/intro-d3/main/data/nigeria-states.json"
	)
]).then(([topoJSONdata, countryData]) => {
	countryData.data.forEach((d) => {
		d.info.Longitude = +d.info.Longitude;
		d.info.Latitude = +d.info.Latitude;
	});
	projection.fitSize([width, height], topoJSONdata);
	g.selectAll("path")
		.data(topoJSONdata.features)
		.join("path")
		.attr("class", "country")
		.attr("d", pathGenerator);

	g.selectAll("circle")
		.data(countryData.data)
		.join("circle")
		.attr("cx", (d) => projection([d.info.Longitude, d.info.Latitude])[0])
		.attr("cy", (d) => projection([d.info.Longitude, d.info.Latitude])[1])
		.attr("r", 5)
		.style("fill", "green");

	g.selectAll("text")
		.data(countryData.data)
		.join("text")
		.attr("x", (d) => projection([d.info.Longitude, d.info.Latitude])[0])
		.attr("y", (d) => projection([d.info.Longitude, d.info.Latitude])[1])
		.attr("dy", -7)
		.style("fill", "black")
		.style("font-size", "18px")
		.attr("text-anchor", "middle")
		.text((d) => d.Name);

	let zooming = d3
		.zoom()
		.scaleExtent([1, 8])
		.extent([
			[0, 0],
			[width, height]
		])
		.on("zoom", function (event) {
			g.selectAll("path").attr("transform", event.transform);
			g.selectAll("circle")
				.attr("transform", event.transform)
				.attr("r", 5 / event.transform.k);
			g.selectAll("text")
				.attr("transform", event.transform)
				.style("font-size", `${18 / event.transform.k}`)
				.attr("dy", -7 / event.transform.k);
		});

	svg.call(zooming);

	d3.select("#zoomIn").on("click", () => {
		svg.transition().call(zooming.scaleBy, 2);
	});
	d3.select("#zoomOut").on("click", () => {
		svg.transition().call(zooming.scaleBy, 0.5);
	});
	d3.select("#resetZoom").on("click", () => {
		svg.transition().call(zooming.scaleTo, 0);
	});
});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.