xxxxxxxxxx
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
<link href='https://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.css' rel='stylesheet' />
<script src="https://d3js.org/d3.v3.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7/leaflet.min.js"></script>
<script src='https://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.js'></script>
<script src='colorlegend.js'></script>
<style>
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
}
#map {
width: 650px;
height: 550px;
}
.travelMarker {
fill: grey;
opacity: 0.75;
}
.waypoints {
fill: black;
opacity: 0;
}
.food {
stroke: black;
fill: red;
}
.lineConnect {
fill: none;
stroke: black;
opacity: 0.25;
}
.locnames {
fill: black;
text-shadow: 1px 1px 1px #FFF, 3px 3px 5px #000;
font-weight: bold;
font-size: 13px;
}
#thedata {
position: absolute;
top: 365px;
left: 0px;
z-index: 10;
width: 220px;
height: 150px;
/* -webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;*/
background: rgba(255, 255, 255, 1);
-webkit-box-shadow: #B3B3B3 4px 4px 4px;
-moz-box-shadow: #B3B3B3 4px 4px 4px;
box-shadow: #B3B3B3 4px 4px 4px;
}
.datacontainer {
padding-top: 10px;
padding-left: 15px;
}
.dataelement {
}
.legend {
width: 200px;
height: 60px;
margin: 10px;
opacity: 1 !important;
padding-left: 15px;
padding-top: 15px;
}
.datatitle {
font-weight: bold;
font-family: "Trebuchet MS", Helvetica, sans-serif;
padding-left: 10px;
opacity: 1;
}
.datavals {
padding-left: 50px;
text-align: left;
font-family: "Trebuchet MS", Helvetica, sans-serif;
}
#no2mean{
padding-left: 19px;
}
</style>
</head>
<body>
<div id="demo"></div>
<div id="map"></div>
<div id="thedata">
<div class="datacontainer">
<div class="dataelement">
<span class="datatitle">Average NO<sub>2</sub>:</span>
<span id="no2mean" class="datavals"></span>
</div>
<div class="dataelement">
<span class="datatitle">Max NO<sub>2</sub>:</span>
<span id="no2max" class="datavals"></span>
</div>
</div>
<div id="legendpieces" class="legend">
</div>
</div>
<script type="text/javascript">
var tweenToggle = 0;
var totalTimeSeconds = 10;
var waypointSize = 3;
//satellite: spatial.ec4cfb76
var mapboxTiles = L.tileLayer('https://{s}.tiles.mapbox.com/v3/examples.map-zr0njcqy/{z}/{x}/{y}.png', {
attribution: '<a href="https://www.mapbox.com/about/maps/" target="_blank">Terms & Feedback</a>',
opacity: 0.75
});
var map = L.map('map')
.addLayer(mapboxTiles)
.setView([40.757, -73.95], 13);
map.scrollWheelZoom.disable()
var svg = d3.select(map.getPanes().overlayPane).append("svg");
var g = svg.append("g").attr("class", "leaflet-zoom-hide");
d3.json("points_pollution_continuous.geojson", function(collection) {
var collectionFeatures = collection.features
featuresdata = collectionFeatures.filter(function(d) {
return d.properties.id == "route1"
})
featuresdata.sort(function(obj1, obj2) {
return obj1.properties.time - obj2.properties.time
})
var maxpollution = d3.max(featuresdata, function(d) {
return d.properties.no2
})
var meanpollution = d3.mean(featuresdata, function(d) {
return d.properties.no2
})
var minpollution = d3.min(featuresdata, function(d) {
return d.properties.no2
})
// create, color, projection and toLine functions
var colorScale = d3.scale.linear()
.domain([minpollution, meanpollution, maxpollution])
.range(["blue", "white", "red"]);
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
});
// here is our stuff - lines and points
var linePath = g.selectAll("path")
.data([featuresdata])
.enter()
.append("path")
.attr("class", "lineConnect");
var marker = g.append("circle")
.attr("r", 20)
.attr("id", "marker")
.attr("class", "travelMarker");
var ptFeatures = g.selectAll("circle")
.data(featuresdata)
.enter()
.append("circle")
.attr("r", waypointSize)
.attr("class", function(d) {
return "waypoints " + "c" + d.properties.time
})
.style("fill", function(d) {
return colorScale(d.properties.no2)
});
var originANDdestination = [featuresdata[0], featuresdata[featuresdata.length - 1]]
var begend = g.selectAll(".food")
.data(originANDdestination)
.enter()
.append("circle", ".food")
.attr("r", 5)
.style("fill", "black")
.style("opacity", "1");
var text = g.selectAll("text")
.data(originANDdestination)
.enter()
.append("text")
.text(function(d, i) {
var tmp = "Lomzynianka Pierogies"
if (i != 1) {
tmp = "Jacob's Pickles"
}
return tmp
})
.attr("class", "locnames")
.attr("y", function(d) {
return -10
});
map.on("viewreset", reset);
reset();
colorlegend("#legendpieces", colorScale,
"linear", {
title: "Nitrogen Dioxide (ppb)",
boxHeight: 20,
boxWidth: 23,
linearBoxes: 7
});
// functions
function reset() {
ptFeatures.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
})
var bounds = d3path.bounds(collection),
topLeft = bounds[0],
bottomRight = bounds[1];
text.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
begend.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
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", toLine)
g.attr("transform", "translate(" + (-topLeft[0] + 50) + "," + (-topLeft[1] + 50) + ")");
transition();
} // end reset
///////////////////////////////////////////////////////////////
function transition(path) {
ptFeatures
.transition()
.style("opacity", 0);
var l = linePath.node().getTotalLength();
segments = [0];
for (var i = 1; i < featuresdata.length; i++) {
var tmp = svg.append("path")
.datum([featuresdata[i - 1], featuresdata[i]])
.attr("d", toLine);
segments.push(segments[i - 1] + tmp.node().getTotalLength());
tmp.remove();
}
ptFeatures.transition()
.delay(function(d, i) {
return (totalTimeSeconds * 1000 * segments[i] / l) - 0
})
.style("opacity", 1);
linePath.transition()
.duration(totalTimeSeconds * 1000)
.ease("linear")
.attrTween("stroke-dasharray", tweenDash)
.each("end", function() {
d3.select(this).call(transition);
});
} //end transition
///////////////////////////////////////////////////////////////
function tweenDash() {
return function(t) {
var l = linePath.node().getTotalLength();
//https://jsfiddle.net/Y62Hq/2/
interpolate = d3.interpolateString("0," + l, l + "," + l);
var marker = d3.select("#marker");
var p = linePath.node().getPointAtLength(t * l);
//enable code for auto re-center
// if (tweenToggle == 0) {
// tweenToggle = 1;
// var newCenter = map.layerPointToLatLng(new L.Point(p.x, p.y));
// map.panTo(newCenter, 14);
// } else {
// tweenToggle = 0;
// }
marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker
// where on the line are we
var currentloc = parseFloat(interpolate(t).split(",")[0])
var seq = [];
for (var i = 0; i != segments.length - 1; ++i) seq.push(i)
sumval = seq.filter(function(d, i) {
return segments[i] < currentloc
});
var no2valsSoFar = featuresdata.slice(0, d3.max(sumval))
var meanNO2 = Math.round(d3.mean(no2valsSoFar, function(d) {
return d.properties.no2
}) * 100) / 100;
var maxNO2 = Math.round(d3.max(no2valsSoFar, function(d) {
return d.properties.no2
}) * 100) / 100;
// console.log(no2valsSoFar.length)
d3.select('#no2mean').text(meanNO2.toFixed(2));
d3.select('#no2max').text(maxNO2.toFixed(2));
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
});
// similar to projectPoint this function converts lat/long to
// svg coordinates except that it accepts a point from our
// GeoJSON
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>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://cdn.leafletjs.com/leaflet-0.7/leaflet.js to a secure url
https://d3js.org/d3.v3.min.js
https://cdn.leafletjs.com/leaflet-0.7/leaflet.js
https://api.tiles.mapbox.com/mapbox.js/v1.6.4/mapbox.js