Я пытаюсь реализовать следующий пример для анимации пути с использованием Leaflet и D3.js: http://zevross.com/blog/2014/09/30/use-the-amazing-d3-library-to-animate-a-path-on-a-leaflet-map/.
В строке 110 появляется сообщение о том, что d не определено, и я не могу найтирешение.Есть идеи, как это решить?
<!DOCTYPE html5>
<html>
<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"
integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"
integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw=="
crossorigin=""></script>
<style>
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
}
#map {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">
// set up the map
map = new L.Map('map');
// create the tile layer with correct attribution
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib='Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
var osm = new L.TileLayer(osmUrl, {minZoom: 8, maxZoom: 15, attribution: osmAttrib});
// start the map in Donosti
map.setView(new L.LatLng(40.72332345541449, -73.99),14);
map.addLayer(osm);
var svg = d3.select(map.getPanes().overlayPane).append("svg");
var g = svg.append("g").attr("class", "leaflet-zoom-hide");
d3.json("points.geojson", function(collection) {
var featuresdata = collection.features.filter(function(d) {
return d.properties.id == "route1"
});
var transform = d3.geo.transform({
point: projectPoint
});
var d3path = d3.geo.path().projection(transform);
var toLine = d3.svg.line()
.interpolate("linear")
.x(function(d) {
return applyLatLngToLayer(d).x
})
.y(function(d) {
return applyLatLngToLayer(d).y
});
var ptFeatures = g.selectAll("circle")
.data(featuresdata)
.enter()
.append("circle")
.attr("r", 3)
.attr("class", "waypoints");
var linePath = g.selectAll(".lineConnect")
.data([featuresdata])
.enter()
.append("path")
.attr("class", "lineConnect");
// This will be our traveling circle it will
// travel along our path
var marker = g.append("circle")
.attr("r", 10)
.attr("id", "marker")
.attr("class", "travelMarker");
var originANDdestination = [featuresdata[0], featuresdata[17]];
var begend = g.selectAll(".drinks")
.data(originANDdestination)
.enter()
.append("circle", ".drinks")
.attr("r", 5)
.style("fill", "red")
.style("opacity", "1");
// I want names for my coffee and beer
var text = g.selectAll("text")
.data(originANDdestination)
.enter()
.append("text")
.text(function(d) {
return d.properties.name
})
.attr("class", "locnames")
.attr("y", function(d) {
return -10
});
// when the user zooms in or out you need to reset
// the view
map.on("viewreset", reset);
// this puts stuff on the map!
reset();
transition();
// Reposition the SVG to cover the features.
function reset() {
var bounds = d3path.bounds(collection),
topLeft = bounds[0],
bottomRight = bounds[1];
text.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
// for the points we need to convert from latlong
// to map units
begend.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
ptFeatures.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
// again, not best practice, but I'm harding coding
// the starting point
marker.attr("transform",
function() {
var y = featuresdata[0].geometry.coordinates[1]
var x = featuresdata[0].geometry.coordinates[0]
return "translate(" +
map.latLngToLayerPoint(new L.LatLng(y, x)).x + "," +
map.latLngToLayerPoint(new L.LatLng(y, x)).y + ")";
});
// Setting the size and location of the overall SVG container
svg.attr("width", bottomRight[0] - topLeft[0] + 120)
.attr("height", bottomRight[1] - topLeft[1] + 120)
.style("left", topLeft[0] - 50 + "px")
.style("top", topLeft[1] - 50 + "px");
// linePath.attr("d", d3path);
linePath.attr("d", toLine)
// ptPath.attr("d", d3path);
g.attr("transform", "translate(" + (-topLeft[0] + 50) + "," + (-topLeft[1] + 50) + ")");
}; // end reset
function transition() {
linePath.transition()
.duration(7500)
.attrTween("stroke-dasharray", tweenDash)
.each("end", function() {
d3.select(this).call(transition);// infinite loop
});
}; //end transition
// this function feeds the attrTween operator above with the
// stroke and dash lengths
function tweenDash() {
return function(t) {
//total length of path (single value)
var l = linePath.node().getTotalLength();
interpolate = d3.interpolateString("0," + l, l + "," + l);
//t is fraction of time 0-1 since transition began
var marker = d3.select("#marker");
// 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 = linePath.node().getPointAtLength(t * l);
//Move the marker to that point
marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker
console.log(interpolate(t))
return interpolate(t);
}
}; //end tweenDash
function projectPoint(x, y) {
var point = map.latLngToLayerPoint(new L.LatLng(y, x));
this.stream.point(point.x, point.y);
}; //end projectPoint
});
function applyLatLngToLayer(d) {
var y = d.geometry.coordinates[1]
var x = d.geometry.coordinates[0]
return map.latLngToLayerPoint(new L.LatLng(y, x))
};
</script>
</body>
</html>
И внешний файл, необходимый для запуска кода:
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature",
"properties": { "latitude": 40.722390, "longitude": -73.995170, "time": 1, "id": "route1", "name":"Gimme" },
"geometry": { "type": "Point", "coordinates": [ -73.99517, 40.72239 ] } },
{ "type": "Feature",
"properties": { "latitude": 40.721580, "longitude": -73.995480, "time": 2, "id": "route1", "name":"Along route" },
"geometry": { "type": "Point", "coordinates": [ -73.99548, 40.72158 ] } }]}