Last active
July 26, 2017 05:19
-
-
Save danhammer/1b80a29f4e09e6277ee95e3c8adb437d to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| {"type": "FeatureCollection", "features": [{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[111.916952,8.642059],[111.916866,8.642154],[111.917188,8.642504],[111.917392,8.642611],[111.917306,8.642717],[111.917467,8.642854],[111.917639,8.642833],[111.91795,8.643173],[111.917886,8.643258],[111.918175,8.643565],[111.91825,8.643979],[111.918154,8.644021],[111.918122,8.643915],[111.918036,8.643936],[111.918122,8.644308],[111.918186,8.644308],[111.918186,8.644255],[111.918358,8.644255],[111.918551,8.645008],[111.918465,8.644976],[111.918454,8.64523],[111.918422,8.645305],[111.918358,8.645315],[111.91839,8.6454],[111.918497,8.645549],[111.918508,8.645655],[111.918433,8.64574],[111.918486,8.645824],[111.918068,8.645803],[111.918068,8.645909],[111.918454,8.645941],[111.918508,8.646037],[111.918433,8.646068],[111.918433,8.646249],[111.918358,8.646249],[111.918293,8.6461],[111.917124,8.646334],[111.917038,8.646249],[111.916641,8.645368],[111.916673,8.645294],[111.91677,8.645305],[111.916791,8.6454],[111.916877,8.645347],[111.916695,8.644891],[111.916587,8.644923],[111.91663,8.64505],[111.916544,8.645124],[111.916448,8.644806],[111.916137,8.644233],[111.916137,8.643756],[111.916255,8.643756],[111.916255,8.643873],[111.916341,8.643873],[111.916351,8.643353],[111.916276,8.643353],[111.916265,8.643459],[111.916169,8.64347],[111.916169,8.643045],[111.916094,8.642992],[111.916029,8.642992],[111.915987,8.643077],[111.915976,8.644255],[111.916888,8.646387],[111.917381,8.646917],[111.918293,8.647299],[111.920278,8.648031],[111.923239,8.649176],[111.923207,8.649314],[111.923625,8.649473],[111.923625,8.649367],[111.924344,8.649664],[111.924977,8.649123],[111.924924,8.64854],[111.923175,8.646641],[111.921587,8.644456],[111.921126,8.643841],[111.92149,8.643533],[111.921619,8.643714],[111.921812,8.643576],[111.921523,8.643194],[111.921362,8.643332],[111.921426,8.643438],[111.921104,8.643745],[111.921072,8.643597],[111.920772,8.643332],[111.920418,8.643067],[111.920246,8.642961],[111.920139,8.642812],[111.919473,8.642207],[111.919398,8.642091],[111.919087,8.641995],[111.918969,8.642048],[111.918776,8.641868],[111.918036,8.641041],[111.918122,8.640956],[111.917757,8.640532],[111.917639,8.640606],[111.917435,8.640532],[111.917145,8.640447],[111.916963,8.640447],[111.916426,8.640882],[111.916373,8.641041],[111.916426,8.641476],[111.916952,8.642059]]]]},"properties":{"cartodb_id":1,"fid":0}}]} |
This file contains hidden or 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
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <style> | |
| path { | |
| fill: #e3e3e3; | |
| stroke-width: 1px; | |
| stroke: #666; | |
| } | |
| circle { | |
| stroke: none; | |
| fill: #fc0; | |
| } | |
| .added { | |
| fill: #f0f; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <svg width="960" height="500"></svg> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script> | |
| <script> | |
| var svg = d3.select("svg"), | |
| path = svg.append("path"), | |
| circles = svg.append("g"); | |
| d3.json("total.topojson", function(err, topo){ | |
| var states = topojson.feature(topo, topo.objects.collection).features.map(function(d){ | |
| return d.geometry.coordinates[0]; | |
| }); | |
| d3.shuffle(states); | |
| draw(); | |
| function draw() { | |
| var a = states[0].slice(0), | |
| b = states[1].slice(0); | |
| // Same number of points on each ring | |
| if (a.length < b.length) { | |
| addPoints(a, b.length - a.length); | |
| } else if (b.length < a.length) { | |
| addPoints(b, a.length - b.length); | |
| } | |
| // Pick optimal winding | |
| a = wind(a, b); | |
| path.attr("d", join(a)); | |
| // Redraw points | |
| //circles.datum(a) | |
| //.call(updateCircles); | |
| // Morph | |
| var t = d3.transition() | |
| .duration(3000); | |
| path.transition(t) | |
| .on("end", function(){ | |
| states.push(states.shift()); | |
| setTimeout(draw, 100); | |
| }) | |
| .attr("d", join(b)); | |
| circles.selectAll("circle").data(b) | |
| .transition(t) | |
| .attr("cx",function(d){ | |
| return d[0]; | |
| }) | |
| .attr("cy",function(d){ | |
| return d[1]; | |
| }); | |
| } | |
| }); | |
| function updateCircles(sel) { | |
| var circles = sel.selectAll("circle") | |
| .data(function(d){ return d; }); | |
| var merged = circles.enter() | |
| .append("circle") | |
| .attr("r", 2) | |
| .merge(circles); | |
| merged.classed("added", function(d){ | |
| return d.added; | |
| }) | |
| .attr("cx",function(d){ | |
| return d[0]; | |
| }) | |
| .attr("cy",function(d){ | |
| return d[1]; | |
| }); | |
| circles.exit().remove(); | |
| } | |
| function addPoints(ring, numPoints) { | |
| var desiredLength = ring.length + numPoints, | |
| step = d3.polygonLength(ring) / numPoints; | |
| var i = 0, | |
| cursor = 0, | |
| insertAt = step / 2; | |
| do { | |
| var a = ring[i], | |
| b = ring[(i + 1) % ring.length]; | |
| var segment = distanceBetween(a, b); | |
| if (insertAt <= cursor + segment) { | |
| ring.splice(i + 1, 0, pointBetween(a, b, (insertAt - cursor) / segment)); | |
| insertAt += step; | |
| continue; | |
| } | |
| cursor += segment; | |
| i++; | |
| } while (ring.length < desiredLength); | |
| } | |
| function pointBetween(a, b, pct) { | |
| var point = [ | |
| a[0] + (b[0] - a[0]) * pct, | |
| a[1] + (b[1] - a[1]) * pct | |
| ]; | |
| point.added = true; | |
| return point; | |
| } | |
| function distanceBetween(a, b) { | |
| return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)); | |
| } | |
| function join(d) { | |
| return "M" + d.join("L") + "Z"; | |
| } | |
| function wind(ring, vs) { | |
| var len = ring.length, | |
| min = Infinity, | |
| bestOffset, | |
| sum; | |
| for (var offset = 0, len = ring.length; offset < len; offset++) { | |
| var sum = d3.sum(vs.map(function(p, i){ | |
| var distance = distanceBetween(ring[(offset + i) % len], p); | |
| return distance * distance; | |
| })); | |
| if (sum < min) { | |
| min = sum; | |
| bestOffset = offset; | |
| } | |
| } | |
| return ring.slice(bestOffset).concat(ring.slice(0, bestOffset)); | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment