Skip to content

Instantly share code, notes, and snippets.

@jhubley
Last active August 29, 2015 14:12
Show Gist options
  • Save jhubley/c22e71c05e3c3bfadcae to your computer and use it in GitHub Desktop.
Save jhubley/c22e71c05e3c3bfadcae to your computer and use it in GitHub Desktop.
vector tiles plus plotted coordinates

A map of some trees in Fort Greene Park, showing Mapbox vector tiles in the background, with tree coordinates plotted on top. Tree coordinates are loaded in with data(). Tree location data gathered by me. I used Mike Bostock's vector tile example as a starting point.

lat long x y name genus species
40 41 23 N 73 58 30 W 40.689722 -73.975 Osage Orange Maclura pomifera
40 41 23 N 73 58 30 W 40.689722 -73.975 Pin Oak Quercus palustris
40 41 23 N 73 58 30 W 40.689722 -73.975 Eastern White Pine Pinus strobus
40 41 23 N 73 58 25 W 40.689722 -73.973611 Magnolia Magnolia
40 41 23 N 73 58 25 W 40.689722 -73.973611 Sugar Maple Acer saccharum
40 41 25 N 73 58 25 W 40.690278 -73.973611 European Beech Fagus sylvatica
40 41 25 N 73 58 26 W 40.690278 -73.973889 English Elm Ulmus minor
40 41 32 N 73 58 31 W 40.692222 -73.975278 Maidenhair Tree Ginkgo biloba
40 41 33 N 73 58 31 W 40.6925 -73.975278 Northern Red Oak Quercus rubra
40 41 32 N 73 58 33 W 40.692222 -73.975833 Black Locust Robinia pseudoacacia
40 41 32 N 73 58 33 W 40.692222 -73.975833 Japanese Zelkova Zelkova serrata
40 41 32 N 73 58 33 W 40.692222 -73.975833 Honey Locust Gleditsia triacanthos
40 41 29 N 73 58 43 W 40.691389 -73.978611 Mulberry Morus
40 41 28 N 73 58 30 W 40.691111 -73.975 Goldenrain Tree Koelreuteria paniculata
40 41 25 N 73 58 35 W 40.690278 -73.976389 White Ash Fraxinus americana
40 41 26 N 73 58 36 W 40.690556 -73.976667 Amur Cork Tree Phellodendron amurense
40 41 26 N 73 58 36 W 40.690556 -73.976667 Black Cherry Prunus serotina
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
margin: 0;
}
#container {
position: relative;
overflow: hidden;
background: #35363b;
}
#map{
width:100%;
height:100%;
}
#points{
width:100%;
height:100%;
position:relative;
z-index:100;
}
.layer {
position: absolute;
}
.tile {
pointer-events: none;
position: absolute;
width: 256px;
height: 256px;
}
.info {
position: absolute;
bottom: 0px;
left: 0px;
padding: 20px;
background: #000;
color: #fff;
width: 100%;
z-index: 1000;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.geo.tile.v0.min.js"></script>
<script>
var width = Math.max(960, window.innerWidth),
height = Math.max(500, window.innerHeight),
prefix = prefixMatch(["webkit", "ms", "Moz", "O"]);
d3.csv("ftgreenetrees.csv", function(error, dataset) { createMap(dataset) });
var tile = d3.geo.tile()
.size([width, height]);
var projection = d3.geo.mercator()
.scale((1 << 25) / 2 / Math.PI)
.translate([-width / 2, -height / 2]); // just temporary
var zoom = d3.behavior.zoom()
.scale(projection.scale() * 2 * Math.PI)
.scaleExtent([1 << 9, 1 << 25])
.translate(projection([-73.975536, 40.691674]).map(function(x) { return -x; }))
.on("zoom", zoomed);
var container = d3.select("body").append("div")
.attr("id", "container")
.style("width", width + "px")
.style("height", height + "px")
.call(zoom)
.on("mousemove", mousemoved);
var map = container.append("g")
.attr("id", "map")
var points = container.append("svg")
.attr("id", "points")
var layer = map.append("div")
.attr("class", "layer");
var info = map.append("div")
.attr("class", "info");
zoomed();
function createMap(dataset) {
d3.select("#points").selectAll("circle").data(dataset) //plotted locations on map
.enter()
.append("circle")
.style("fill", "#14e6b7")
.style("opacity", 0.7)
.attr("r", 8)
.attr("cx", function(d) {return projection([d.y,d.x])[0]})
.attr("cy", function(d) {return projection([d.y,d.x])[1]})
zoomed();
}
function zoomed() {
var tiles = tile
.scale(zoom.scale())
.translate(zoom.translate())
();
projection
.scale(zoom.scale() / 2 / Math.PI)
.translate(zoom.translate());
d3.selectAll("circle")
.attr("cx", function(d) {return projection([d.y,d.x])[0]})
.attr("cy", function(d) {return projection([d.y,d.x])[1]})
var image = layer
.style(prefix + "transform", matrix3d(tiles.scale, tiles.translate))
.selectAll(".tile")
.data(tiles, function(d) { return d; });
image.exit()
.remove();
image.enter().append("img")
.attr("class", "tile")
.attr("src", function(d) { return "http://" + ["a", "b", "c", "d"][Math.random() * 4 | 0] + ".tiles.mapbox.com/v3/jhubley.kllla0l7/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; })
.style("left", function(d) { return (d[0] << 8) + "px"; })
.style("top", function(d) { return (d[1] << 8) + "px"; });
}
function mousemoved() {
info.text(formatLocation(projection.invert(d3.mouse(this)), zoom.scale()));
}
function matrix3d(scale, translate) {
var k = scale / 256, r = scale % 1 ? Number : Math.round;
return "matrix3d(" + [k, 0, 0, 0, 0, k, 0, 0, 0, 0, k, 0, r(translate[0] * scale), r(translate[1] * scale), 0, 1 ] + ")";
}
function prefixMatch(p) {
var i = -1, n = p.length, s = document.body.style;
while (++i < n) if (p[i] + "Transform" in s) return "-" + p[i].toLowerCase() + "-";
return "";
}
function formatLocation(p, k) {
var format = d3.format("." + Math.floor(Math.log(k) / 2 - 2) + "f");
return (p[1] < 0 ? format(-p[1]) + "°S" : format(p[1]) + "°N") + " "
+ (p[0] < 0 ? format(-p[0]) + "°W" : format(p[0]) + "°E");
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment