Based on /maciejkus/61e9ff1591355b00c1c1caf31e76a668
Redone for d3.js v4
Infinite pan by reprojecting path data at origial scale
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {
background-color: white;
}
svg {
border: 2px solid black;
background-color: white;
}
.boundary {
fill: #DEB887;
stroke: black;
stroke-width: 1px;
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v4.js"></script>
<!--<script src="https://d3js.org/topojson.v2.min.js"></script>-->
<script src="https://unpkg.com/topojson-client@3"></script>
<script>
var width = 900,
height = 500;
var initX;
var mouseClicked = false;
var s = 1;
var rotated = 90;
//need to store this because on zoom end, using mousewheel, mouse position is NAN
var mouse;
var projection = d3.geoMercator()
.scale(153)
.translate([width/2,height/1.5])
.rotate([rotated,0,0]); //center on USA
var path = d3.geoPath().projection(projection);
var zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed)
.on("end", zoomended);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.on("wheel", function() {
//zoomend needs mouse coords
initX = d3.mouse(this)[0];
})
.on("mousedown", function() {
//only if scale === 1
if(s !== 1) return;
initX = d3.mouse(this)[0];
mouseClicked = true;
})
.call(zoom);
var g = svg.append("g");
function rotateMap(endX) {
projection.rotate([rotated + (endX - initX) * 360 / (s * width),0,0]);
g.selectAll('path').attr('d', path);
}
function zoomended(){
if(s !== 1) return;
//rotated = rotated + ((d3.mouse(this)[0] - initX) * 360 / (s * width));
rotated = rotated + ((mouse[0] - initX) * 360 / (s * width));
mouseClicked = false;
}
function zoomed() {
var t = [d3.event.transform.x,d3.event.transform.y];
s = d3.event.transform.k;
var h = 0;
t[0] = Math.min(
(width/height) * (s - 1),
Math.max( width * (1 - s), t[0] )
);
t[1] = Math.min(
h * (s - 1) + h * s,
Math.max(height * (1 - s) - h * s, t[1])
);
g.attr("transform", "translate(" + t + ")scale(" + s + ")");
//adjust the stroke width based on zoom level
d3.selectAll(".boundary").style("stroke-width", 1 / s);
mouse = d3.mouse(this);
if(s === 1 && mouseClicked) {
//rotateMap(d3.mouse(this)[0]);
rotateMap(mouse[0]);
return;
}
}
d3.json("https://unpkg.com/world-atlas@1/world/110m.json", function(error, world) {
if(error) return console.error(error);
//countries
g.append("g")
.attr("class", "boundary")
.selectAll("boundary")
.data(topojson.feature(world, world.objects.countries).features)
.enter().append("path")
.attr("d", path);
});
</script>
</body>
https://d3js.org/d3.v4.js
https://d3js.org/topojson.v2.min.js
https://unpkg.com/topojson-client@3