JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-fetch.v1.min.js"></script>
<head>
<script src="json/world.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/d3-fetch.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinycolor/1.4.1/tinycolor.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/index.min.js"></script>
<title></title>
</head>
<body>
<h1>Life Expectancy of the World Between 2000-2019</h1>
<div style="display:flex; align-items: center">
<!-- These styles create the bounding box-->
<div style="overflow: hidden; border: 1px solid black; background: ivory">
<div class="home"></div>
</div>
<div style="margin-left: 24px">
<h2 id="currentYear">2000</h2>
<button style="background: rgb(240,246,253)" onclick="subtractYearAndRerender()">
<
</button>
<button style="background: rgb(244,249,254)" onclick="addYearAndRerender()">
>
</button>
</div>
</div>
</body>
CSS
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: "Open Sans", sans-serif;
}
.country {
stroke-width: 1;
stroke: darkslategrey;
fill: white;
transition: all 0.25s ease-in-out;
}
.country:hover {
cursor: pointer;
fill: #555555;
}
div.tooltip {
text-align: center;
min-width: 60px;
transition: opacity 0.25s ease-in-out;
min-height: 28px;
padding: 8px 12px;
font: 12px sans-serif;
background: white;
border: 1px solid lightgray;
border-radius: 4px;
pointer-events: none;
}
button {
background: transparent;
border: 1px solid lightgray;
border-radius: 4px;
padding: 4px 16px;
transition: all 0.25s ease-in-out;
}
button:hover {
cursor: pointer;
border: 1px solid darkgray;
}
JavaScript
function addYearAndRerender() {
currentYear = currentYear + 1;
reRender(currentYear);
}
function subtractYearAndRerender() {
currentYear = currentYear - 1;
reRender(currentYear);
}
let currentYear = 2000;
let lifeExpectancyCsv = 'https://raw.githubusercontent.com/Bradleykingz/working-with-d3/master/files/life-expectancy.csv';
let worldMapJson = 'https://raw.githubusercontent.com/Bradleykingz/working-with-d3/master/files/world.geo.json'
const width = 1000;
const height = 700;
const projection = d3.geoMercator()
.translate([width / 2, window.innerHeight / 1.4]) // translate to center of screen
.scale([150]);
const path = d3.geoPath().projection(projection);
let zoom = d3.zoom()
.scaleExtent([1, 10])
.translateExtent([[-500,-300], [1500, 1000]])
.on('zoom', () => {
svg.attr('transform', d3.event.transform)
});
const container = d3.select(".home");
const svg = container.append("svg");
const tooltip = d3.tip().attr('class', 'tooltip')
.html(function (d) {
return `<div>
<p>Country: ${d.entity}</p>
<p>Life expectancy: ${d.lifeExpectancy}</p>
</div>`;
});
svg.attr("width", width)
.attr("height", height)
.style("background", 'ivory')
.append('g')
.call(tooltip);
container.call(zoom);
const render = (path, data, scale) => svg.selectAll()
.data(data)
.enter()
.append('path')
.attr('d', path)
.attr('class', 'country')
.style('fill', function (d) {
return scale(d.lifeExpectancy);
}).on('mouseover', function (d) {
d3.select(this)
.style('fill', tinycolor(scale(d.lifeExpectancy)).darken(10).toString());
tooltip.show(d, this)
})
.on('mouseout', function (d) {
...