An experiment in adding a tile.transform function.
See d3/d3-tile#4.
license: gpl-3.0 |
An experiment in adding a tile.transform function.
See d3/d3-tile#4.
// Build from commit caaa1b44268477ebcc60ad466acec35753373b8f | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-zoom')) : | |
typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-zoom'], factory) : | |
(factory((global.d3 = global.d3 || {}),global.d3,global.d3)); | |
}(this, function (exports,d3Array,d3Zoom) { 'use strict'; | |
function tile() { | |
var x0 = 0, | |
y0 = 0, | |
x1 = 960, | |
y1 = 500, | |
tx = (x0 + x1) / 2, | |
ty = (y0 + y1) / 2, | |
scale = 256, | |
zoomDelta = 0; | |
function tile() { | |
var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0), | |
z0 = Math.round(z + zoomDelta), | |
k = Math.pow(2, z - z0 + 8), | |
x = tx - scale / 2, | |
y = ty - scale / 2, | |
tiles = [], | |
cols = d3Array.range(Math.max(0, Math.floor((x0 - x) / k)), Math.max(0, Math.ceil((x1 - x) / k))), | |
rows = d3Array.range(Math.max(0, Math.floor((y0 - y) / k)), Math.max(0, Math.ceil((y1 - y) / k))); | |
rows.forEach(function(y) { | |
cols.forEach(function(x) { | |
tiles.push([x, y, z0]); | |
}); | |
}); | |
tiles.translate = [x / k, y / k]; | |
tiles.scale = k; | |
tiles.transform = d3Zoom.zoomIdentity | |
.scale(tiles.scale) | |
.translate(tiles.translate[0], tiles.translate[1]); | |
return tiles; | |
} | |
tile.size = function(_) { | |
return arguments.length ? (x0 = y0 = 0, x1 = +_[0], y1 = +_[1], tile) : [x1, y1]; | |
}; | |
tile.extent = function(_) { | |
return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], tile) : [[x0, y0], [x1, y1]]; | |
}; | |
tile.scale = function(_) { | |
return arguments.length ? (scale = +_, tile) : scale; | |
}; | |
tile.translate = function(_) { | |
return arguments.length ? (tx = +_[0], ty = +_[1], tile) : [tx, ty]; | |
}; | |
tile.transform = function(_) { | |
if(arguments.length){ | |
return tile.scale(_.k).translate([_.x, _.y]); | |
} else { | |
return d3Zoom.zoomIdentity.translate(tx, ty).scale(scale); | |
} | |
}; | |
tile.zoomDelta = function(_) { | |
return arguments.length ? (zoomDelta = +_, tile) : zoomDelta; | |
}; | |
return tile; | |
} | |
exports.tile = tile; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
})); |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
margin: 0; | |
} | |
path { | |
fill: none; | |
stroke: red; | |
stroke-linejoin: round; | |
stroke-width: 1.5px; | |
} | |
</style> | |
<body> | |
<script src="//d3js.org/d3.v4.0.0-alpha.50.min.js"></script> | |
<script src="//d3js.org/topojson.v1.min.js"></script> | |
<script src="d3-tile.js"></script> | |
<script> | |
var width = Math.max(960, window.innerWidth), | |
height = Math.max(500, window.innerHeight); | |
var tile = d3.tile() | |
.size([width, height]); | |
var projection = d3.geoMercator() | |
.scale((1 << 12) / 2 / Math.PI) | |
.translate([width / 2, height / 2]); | |
var center = projection([-100, 40]); | |
var path = d3.geoPath() | |
.projection(projection); | |
var zoom = d3.zoom() | |
.scaleExtent([1 << 11, 1 << 14]) | |
.on("zoom", zoomed); | |
var initialTransform = d3.zoomIdentity | |
.translate(width - center[0], height - center[1]) | |
.scale(projection.scale() * 2 * Math.PI) | |
// With the center computed, now adjust the projection such that | |
// it uses the zoom behavior’s translate and scale. | |
projection | |
.scale(1 / 2 / Math.PI) | |
.translate([0, 0]); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var raster = svg.append("g"); | |
var vector = svg.append("path"); | |
d3.json("https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/us.json", function(error, us) { | |
if (error) throw error; | |
svg.call(zoom).call(zoom.transform, initialTransform); | |
vector.attr("d", path(topojson.mesh(us, us.objects.counties))); | |
}); | |
function zoomed() { | |
var transform = d3.event.transform; | |
var tiles = tile.transform(transform)(); | |
console.log("transform in " + transform); | |
console.log("transform out " + tile.transform()); | |
vector | |
.attr("transform", transform) | |
.style("stroke-width", 1 / transform.k); | |
var image = raster | |
.attr("transform", tiles.transform) | |
.selectAll("image") | |
.data(tiles, function(d) { return d; }); | |
image.exit() | |
.remove(); | |
image.enter().append("image") | |
.attr("xlink:href", function(d) { return "http://" + ["a", "b", "c"][Math.random() * 3 | 0] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; }) | |
.attr("width", 1) | |
.attr("height", 1) | |
.attr("x", function(d) { return d[0]; }) | |
.attr("y", function(d) { return d[1]; }); | |
} | |
</script> |