Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This gist creates a map component that draws a map of the US and then transitions the US capitals onto the map in a pleasing way.
// @ts-nocheck
import React, { FC, useLayoutEffect, useCallback } from 'react';
import * as d3 from 'd3';
import * as topojson from 'topojson';
import * as statesMap from '../data/states-albers-10m.json';
import * as cities from '../data/us-cities.json';
export const USMap: FC = () => {
const projection = d3.geoAlbersUsa().scale(1300).translate([487.5, 305])
const path = d3.geoPath();
const us = statesMap.default;
const data = cities.default;
const mapWidth = 975;
const mapHeight = 610;
const translateDiagonal = useCallback((option1, option2, option3) => {
return `translate(${mapWidth * (option2 / option3.length)} ${mapHeight * (option2 / option3.length)})`
}, [mapWidth, mapHeight]);
const translateLongLat = useCallback((option1, option2, option3) => {
return `translate(${option3[option2].getAttribute('originalx')},
${option3[option2].getAttribute('originaly')})`
}, []);
useLayoutEffect(() => {
if (d3) {
d3.selectAll('#parentG > g').transition()
.attr('transform', translateDiagonal)
.transition()
.duration(2000)
.attr('transform', translateLongLat)
}
}, [d3])
const map = <svg viewBox={`0 0 ${mapWidth} ${mapHeight}`}>
<path fill='#ddd' d={`${path(topojson.feature(us, us.objects.nation))}`}></path>
<path fill='none' stroke='#fff' strokeLinejoin='round' strokeLinecap='round' d={`${path(topojson.mesh(us, us.objects.states, (a, b) => a !== b))}`}></path>
<g id='parentG' textAnchor='middle' fontFamily='sans-serif' fontSize='10' style={{ position: 'relative' }}>
{
data.map(({ capital, lat, long }, index, array) => {
const projected = projection([long, lat]);
const projectedX = projection([long, lat])[0];
const projectedY = projection([long, lat])[1];
return (
projected ? <g
originalx={projectedX}
originaly={projectedY}
>
<defs>
<radialGradient id='grad1' >
<stop offset='10%' stopColor='#209cee' stopOpacity={.1} />
<stop offset='90%' stopColor='#050' stopOpacity={.8} />
</radialGradient>
</defs>
<circle r='4' fill='url(#grad1)' ></circle>
<text y='-6'>{capital}</text>
</g>
: null
)
}
)
}
</g>
</svg>
return <div style={{ width: '100%', height: '100%' }}>{map}</div>
}
@Jon20111
Copy link
Author

Jon20111 commented Apr 23, 2020

Wrote up some details of the code here with a video of the animation.

Data for the map can be found here:
https://github.com/topojson/us-atlas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment