Created
April 23, 2020 17:50
-
-
Save Jon20111/232773269475cef1e076a9287cad9ba1 to your computer and use it in GitHub Desktop.
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @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> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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