Transforming geographic shapes into circles with the help of polymorph. Code written in livescript.
Built with blockbuilder.org
license: mit |
Transforming geographic shapes into circles with the help of polymorph. Code written in livescript.
Built with blockbuilder.org
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> </meta> | |
<script src='https://d3js.org/d3.v3.min.js' charset="utf-8"></script> | |
<script src="https://d3js.org/topojson.v1.min.js" charset="utf-8"></script> | |
<script src='https://polyshrink.s3.amazonaws.com/polymorph.js' charset='utf-8'></script> | |
<script src="https://polyshrink.s3.amazonaws.com/countries.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/livescript/1.5.0/livescript.js"></script> | |
<script type="text/ls"> | |
pageWidth = window.innerWidth | |
pageHeight = window.innerHeight | |
proj = new d3.geo.mercator! | |
.center [-105,51] | |
.rotate [0,0,0] | |
.translate [(pageWidth/2),pageHeight/2] | |
.scale 1 .<<. 8 | |
zoomed = -> | |
transform = "translate(#{zoom.translate!}) scale(#{zoom.scale!})" | |
d3.select 'svg#map-canvas g' | |
.attr 'transform', transform | |
.selectAll 'path' | |
.style 'stroke-width', -> 3 / zoom.scale! | |
zoom = new d3.behavior.zoom!on 'zoom', zoomed | |
g = d3.select 'div#map' | |
.append 'svg' | |
.attr 'id', 'map-canvas' | |
.call zoom | |
.append 'g' | |
path = d3.geo.path().projection(proj) # Path generating function | |
# Transpose a shape onto a circle | |
circleIt = (it,x,y,r) -> | |
from = path it # The coastline boundary | |
# A simple circle path of two arcs | |
circle = "m #{x - r} #y | |
a #r #r 0 1 0 #{2*r} 0 | |
a #r #r 0 1 0 #{-2*r} 0" | |
polymorph.transpose from, circle | |
randomCircle = -> | |
p = 20 # padding | |
w = pageWidth - (2 * p) | |
h = pageHeight - (2 * p) | |
x = (Math.random! * w) + p | |
y = (Math.random! * h) + p | |
r = (Math.log it.properties.AREA) * 3 | |
circleIt it, x, y, r | |
colours = | |
Canada: '#CACACA' | |
Mexico: '#8C8787' | |
'United States': '#4E4E4E' | |
cstGeoJson = topojson.feature countries,countries.objects.countries | |
g.selectAll 'path' | |
.data cstGeoJson.features.filter -> # Let's be selective | |
name = it.properties.name | |
area = it.properties.AREA # Filter out small island | |
reg = /(Canada|Mexico|United States)/ # Only NA for now | |
if name.match reg and area > 1 then yes else no | |
.enter! | |
.append 'path' | |
.attr 'd', randomCircle | |
.style 'fill', -> colours[it.properties.name] | |
toDots = -> | |
l = d3.selectAll('path')[0].length | |
i = 1 | |
d3.selectAll 'path' | |
.transition! | |
.delay -> Math.random! * 1000 | |
.duration 5000 | |
.attr 'd', randomCircle | |
.each 'end', -> toCountries! if l is i++ | |
toCountries = -> | |
l = d3.selectAll('path')[0].length | |
i = 1 | |
d3.selectAll 'path' | |
.transition! | |
.delay -> Math.random! * 1000 | |
.duration 5000 | |
.attr 'd', path | |
.each 'end', -> toDots! if l is i++ | |
toCountries! | |
</script> | |
<style> | |
body,html,svg,div#map { | |
width: 100%; | |
height: 100%; | |
padding: 0px; | |
margin: 0px; | |
overflow: hidden; | |
} | |
body { | |
background-color: #ffffff; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<script> | |
var LiveScript = require("livescript"); | |
LiveScript.go(); | |
</script> | |
</body> |