Created
September 19, 2014 17:42
Revisions
-
zross created this gist
Sep 19, 2014 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,226 @@ <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" /> <script src="http://d3js.org/d3.v3.min.js" type="text/javascript"></script> <script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script> <script src='https://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.js'></script> <link href='https://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.css' rel='stylesheet' /> <style> html, body { height: 100%; width: 100%; } body { margin: 0; } #map { width: 100%; height: 100%; } svg { position: relative; } path { fill: none; stroke-width: 4px; stroke: black; stroke-opacity: 0.5; } path.true { stroke: #3366FF; } path.false { stroke: #990099; } circle { fill: yellow; opacity: 0.75; } .area { fill: #3366FF; } .empty { fill: #990099; } </style> </head> <body> <div id="demo"></div> <div id="map"></div> <script type="text/javascript"> var mapboxTiles = L.tileLayer('https://{s}.tiles.mapbox.com/v3/examples.map-zr0njcqy/{z}/{x}/{y}.png', { attribution: '<a href="http://www.mapbox.com/about/maps/" target="_blank">Terms & Feedback</a>' }); var map = L.map('map') .addLayer(mapboxTiles) .setView([40.72332345541449, -74.00390625], 10); // we will be appending the SVG to the Leaflet map pane // g (group) element will be inside the svg and it svg = d3.select(map.getPanes().overlayPane).append("svg"), // if you don't include the leaflet-zoom-hide when a // user zooms in or out you will still see the phantom // original SVG g = svg.append("g").attr("class", "leaflet-zoom-hide"); //read in the GeoJSON. This function is asynchronous so // anything that needs the json file should be within d3.json("linestring2.json", function(collection) { //stream transform. transforms geometry before passing it to // listener. Can be used in conjunction with d3.geo.path // to implement the transform. In this case the transform var transform = d3.geo.transform({ point: projectPoint }); //d3.geo.path translates GeoJSON to SVG path codes. //essentially a path generator. In this case it's // a path generator referencing our custom "projection" // which is the Leaflet method latLngToLayerPoint inside // our function called projectPoint var d3path = d3.geo.path().projection(transform); //essentially we're appending our features to the // group element. We're adding a class with the line name // and we're making them invisible var lineFeatures = g.selectAll("path") .data(collection.features) .enter() .append("path") .attr("class", function(d) { return d.properties.name }) .attr("style", "opacity:0.5"); // this is going to be the circle that tracks the // route, we're appending it to the g element var marker = g.append("circle"); marker.attr("r", 10) .attr("id", "marker"); // for now we're selecting just one of the lines. And // on this one line we're invoking (with the selection.call) // our transition function. Using callis the same as invoking // the function by hand but makes it easier to use method // chaining. var path = svg.select("path.line0") .attr("style", "opacity:1") .call(transition); // when the user zooms in or out you need to reset // the view map.on("viewreset", reset); // this puts stuff on the map! Without this "path" // only exists in theory reset(); var startPoint = pathStartPoint(path); marker.attr("transform", "translate(" + startPoint[0] + "," + startPoint[1] + ")"); // Reposition the SVG to cover the features. function reset() { var bounds = d3path.bounds(collection), topLeft = bounds[0], bottomRight = bounds[1]; // here you're setting some styles, width, heigh etc // to the SVG. Note that we're adding a little height and // width because otherwise the bounding box would perfectly // cover our features BUT... since you might be using a big // circle to represent a 1 dimensional point, the circle // might get cut off. svg.attr("width", bottomRight[0] - topLeft[0] + 100) .attr("height", bottomRight[1] - topLeft[1] + 100) .style("left", topLeft[0] - 50 + "px") .style("top", topLeft[1] - 50 + "px"); lineFeatures.attr("d", d3path); g.attr("transform", "translate(" + (-topLeft[0] + 50) + "," + (-topLeft[1] + 50) + ")" ); }// end reset function pathStartPoint(path) { var d = path.attr('d'); console.log(d) dsplitted = d.split("L")[0].slice(1).split(","); var point = [] point[0] = parseInt(dsplitted[0]); point[1] = parseInt(dsplitted[1]); return point; }//end pathStartPoint function transition(path) { path.transition() .duration(7500) .attrTween("stroke-dasharray", tweenDash); //if you want to have it repeat the sequence // then uncomment this piece //.each("end", function() { // d3.select(this).call(transition); //}); // infinite loop } //end transition function tweenDash() { var l = path.node().getTotalLength(); //total length of path var i = d3.interpolateString("0," + l, l + "," + l); // interpolation of stroke-dasharray style attr console.log(l) return function(t) { //t is fraction of time 0-1 since transition began var marker = d3.select("#marker"); console.log(t) // p is the point on the line (coordinates) at a given length // along the line. In this case if l=50 and we're midway through // the time then this would 25. var p = path.node().getPointAtLength(t * l); //Move the marker to that point marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker return i(t); } } //end tweenDash // Use Leaflet to implement a D3 geometric transformation. // the latLngToLayerPoint is a Leaflet conversion method: //Returns the map layer point that corresponds to the given geographical // coordinates (useful for placing overlays on the map). function projectPoint(x, y) { var point = map.latLngToLayerPoint(new L.LatLng(y, x)); this.stream.point(point.x, point.y); }//end projectPoint }); </script> </body> </html> 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,99 @@ { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {"name":"line0"}, "geometry": { "type": "LineString", "coordinates": [ [ -73.93592834472656, 40.85329308567513 ], [ -73.94210815429688, 40.826799936046804 ], [ -73.96408081054688, 40.7909394098518 ], [ -73.99978637695312, 40.75557964275591 ], [ -73.9990997314453, 40.73529128534676 ], [ -73.99772644042969, 40.71499673906409 ], [ -73.98468017578125, 40.691051628010236 ], [ -73.96614074707031, 40.65615965408628 ], [ -73.93592834472656, 40.63896734381723 ], [ -73.89266967773438, 40.640530464129945 ], [ -73.86657714843749, 40.65563874006118 ], [ -73.8446044921875, 40.70042247927178 ], [ -73.81782531738281, 40.71551718935035 ], [ -73.80340576171875, 40.73164913017892 ] ] } }, { "type": "Feature", "properties": {"name":"line1"}, "geometry": { "type": "LineString", "coordinates": [ [ -73.96133422851562, 40.76806170936614 ], [ -73.93867492675781, 40.75818026660039 ], [ -73.91189575195312, 40.73321007823572 ], [ -73.91876220703125, 40.70510741061974 ], [ -73.85284423828125, 40.72124187397379 ] ] } } ] }