File size: 2,271 Bytes
867080c b4a0c57 7cdde63 92d8154 7cdde63 92d8154 7cdde63 92b2164 00e463a 867080c 00e463a b4a0c57 00e463a 867080c 00e463a 867080c b4a0c57 867080c 92d8154 867080c 7cdde63 867080c 92d8154 00e463a 867080c 00e463a 7cdde63 00e463a 92d8154 7cdde63 00e463a 867080c 92d8154 867080c 7cdde63 92d8154 7cdde63 867080c b4a0c57 867080c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
import { useRef, useEffect, useState } from 'react'
import * as Plot from '@observablehq/plot'
const smoothProgressBar = fraction => {
const blocks = ['▏', '▎', '▍', '▌', '▋', '▊', '▉', '█']
const width = 10
const totalUnits = width * 8
const filledUnits = Math.round(fraction * totalUnits)
const fullBlocks = Math.floor(filledUnits / 8)
const remainder = filledUnits % 8
return (
'█'.repeat(fullBlocks) + (remainder > 0 ? blocks[remainder - 1] : '') || '▏'
)
}
const makeTitle = data => d => {
const languages = data[d.properties?.ISO_A2_EH]?.languages.toSorted(
(a, b) => b.population - a.population
)
const pop = languages?.map(a => a.population).reduce((prev, a) => prev + a, 0)
const langstring =
languages
?.slice(0, 10)
.map(a => `${smoothProgressBar(a.population / pop)} ${a.name}`)
.join('\n\n') + (languages?.length > 10 ? `\n\n...` : '')
return `${d.properties.ADMIN}\n\n${langstring}`
}
const WorldMap = ({ data }) => {
const containerRef = useRef()
const [mapData, setMapData] = useState()
useEffect(() => {
fetch('/world.geo.json')
.then(res => res.json())
.then(setMapData)
}, [])
useEffect(() => {
console.log('countries', data)
if (mapData === undefined || data === undefined) return
const countriesDict = data.reduce((acc, country) => {
acc[country.iso2] = country
return acc
}, {})
const plot = Plot.plot({
width: 750,
height: 500,
projection: 'equal-earth',
marks: [
Plot.geo(mapData, {
fill: d => countriesDict[d.properties?.ISO_A2_EH]?.score,
title: makeTitle(countriesDict),
tip: true
})
],
color: {
scheme: 'Greens',
unknown: 'gray',
label: 'Score',
legend: true,
domain: [0, 0.7]
},
style: {
fontFamily: 'monospace'
}
})
containerRef.current.append(plot)
return () => plot.remove()
}, [mapData, data])
return (
<div
ref={containerRef}
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
/>
)
}
export default WorldMap
|