我正在尝试复制Jason Davies"旋转世界"中显示的缩放功能。可视化(https://www.jasondavies.com/maps/rotate/)
我可以旋转和缩放,但是,如果我在旋转后进行缩放,我的投影会以一个角度缩放(意味着,如果我将地球向左转15度然后缩放,则地球不再保持居中画布)。以下是我的代码,非常感谢任何帮助!
d3.select(window)
.on("mousemove", mousemove)
.on("mouseup", mouseup);
var width = 960,
height = 500;
var proj = d3.geo.orthographic()
.scale(220)
.translate([width / 2, height / 2])
.clipAngle(90);
var path = d3.geo.path().projection(proj).pointRadius(1.5);
var graticule = d3.geo.graticule();
var svg = d3.select("#content").append("svg")
.attr("width", width)
.attr("height", height)
.on("mousedown", mousedown);
var zoom = d3.behavior.zoom()
.center([width / 2, height / 2])
//.scaleExtent([.5, 10])
.on("zoom", zoomed);
svg.call(zoom);
queue()
.defer(d3.json, "/static/json/world.json")
.await(ready);
function ready(error, world) {
/*
Define gradients
*/
// ocean
var ocean_fill = svg.append("defs").append("radialGradient")
.attr("id", "ocean_fill")
.attr("cx", "75%")
.attr("cy", "25%");
ocean_fill.append("stop").attr("offset", "5%").attr("stop-color", "#777");
ocean_fill.append("stop").attr("offset", "100%").attr("stop-color", "#555");
// globe highlight
var globe_highlight = svg.append("defs").append("radialGradient")
.attr("id", "globe_highlight")
.attr("cx", "75%")
.attr("cy", "25%");
globe_highlight.append("stop")
.attr("offset", "5%").attr("stop-color", "#bbb")
.attr("stop-opacity","0.6");
globe_highlight.append("stop")
.attr("offset", "100%").attr("stop-color", "#999")
.attr("stop-opacity","0.2");
// globe shadow
var globe_shading = svg.append("defs").append("radialGradient")
.attr("id", "globe_shading")
.attr("cx", "50%")
.attr("cy", "40%");
globe_shading.append("stop")
.attr("offset","50%").attr("stop-color", "#333")
.attr("stop-opacity","0");
globe_shading.append("stop")
.attr("offset","100%").attr("stop-color", "#111")
.attr("stop-opacity","0.3");
// drop shadow
var drop_shadow = svg.append("defs").append("radialGradient")
.attr("id", "drop_shadow")
.attr("cx", "50%")
.attr("cy", "50%");
drop_shadow.append("stop")
.attr("offset","20%").attr("stop-color", "#000")
.attr("stop-opacity",".5");
drop_shadow.append("stop")
.attr("offset","100%").attr("stop-color", "#000")
.attr("stop-opacity","0");
/*
Draw globe objects
*/
// drop shadow
svg.append("ellipse")
.attr("cx", 440).attr("cy", 450)
.attr("rx", proj.scale()*.90)
.attr("ry", proj.scale()*.25)
.attr("class", "noclicks")
.style("fill", "url(#drop_shadow)");
// globe
svg.append("circle")
.attr("cx", width / 2).attr("cy", height / 2)
.attr("r", proj.scale())
.attr("class", "noclicks")
.style("fill", "url(#ocean_fill)");
// land
svg.append("path")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
svg.append("path")
.datum(graticule)
.attr("class", "graticule noclicks")
.attr("d", path);
svg.append("circle")
.attr("cx", width / 2).attr("cy", height / 2)
.attr("r", proj.scale())
.attr("class","noclicks")
.style("fill", "url(#globe_highlight)");
svg.append("circle")
.attr("cx", width / 2).attr("cy", height / 2)
.attr("r", proj.scale())
.attr("class","noclicks")
.style("fill", "url(#globe_shading)");
/* svg.append("g").attr("class","points")
.selectAll("text").data(places.features)
.enter().append("path")
.attr("class", "point")
.attr("d", path);
svg.append("g").attr("class","labels")
.selectAll("text").data(places.features)
.enter().append("text")
.attr("class", "label")
.text(function(d) { return d.properties.name })*/
svg.append("g").attr("class","countries")
.selectAll("path")
.data(topojson.feature(world2, world2.objects.countries).features)
.enter().append("path")
.attr("d", path);
}
// modified from http://bl.ocks.org/1392560
var m0, o0;
function mousedown() {
m0 = [d3.event.pageX, d3.event.pageY];
o0 = proj.rotate();
d3.event.preventDefault();
}
function mousemove() {
if (m0) {
var m1 = [d3.event.pageX, d3.event.pageY]
, o1 = [o0[0] + (m1[0] - m0[0]) / 6, o0[1] + (m0[1] - m1[1]) / 6];
o1[1] = o1[1] > 30 ? 30 :
o1[1] < -30 ? -30 :
o1[1];
proj.rotate(o1);
refresh();
}
}
function mouseup() {
if (m0) {
mousemove();
m0 = null;
}
}
function refresh() {
svg.selectAll(".land").attr("d", path);
svg.selectAll(".countries path").attr("d", path);
svg.selectAll(".graticule").attr("d", path);
svg.selectAll(".point").attr("d", path);
//position_labels();
}
var slast = 1;
function zoomed() {
if (slast != d3.event.scale) {
svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
slast = d3.event.scale;
};
}