缩放时如何保持d3正交投影居中

2024-02-12

我正在尝试复制 Jason Davies“旋转世界”可视化中显示的缩放功能(https://www.jasondavies.com/maps/rotate/ 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;
    };
}

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

缩放时如何保持d3正交投影居中 的相关文章