Skip to content

Instantly share code, notes, and snippets.

@popkinj
Last active September 26, 2016 19:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save popkinj/747032288bb696cb1ad0433c8821b188 to your computer and use it in GitHub Desktop.
Save popkinj/747032288bb696cb1ad0433c8821b188 to your computer and use it in GitHub Desktop.
Morphing Geographic Boundaries
license: mit
<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment