D3:我用什么投影? /如何简化空投影?

时间:2013-09-27 14:24:26

标签: d3.js map-projections simplification

我正在尝试在缩放时简化d3地图,我使用this example作为起点。但是,当我用自己的(http://weather-bell.com/res/nws_regions.topojson)替换示例中的json文件时,我会得到一个小小的倒置小地图。

这是我的jsfiddle:http://jsfiddle.net/8ejmH 代码:

var width = 900,
    height = 500;

var chesapeake = [-75.959, 38.250];

var scale,
translate,
visibleArea, // minimum area threshold for points inside viewport
invisibleArea; // minimum area threshold for points outside viewport

var simplify = d3.geo.transform({
    point: function (x, y, z) {
        if (z < visibleArea) return;
        x = x * scale + translate[0];
        y = y * scale + translate[1];
        if (x >= 0 && x <= width && y >= 0 && y <= height || z >= invisibleArea) this.stream.point(x, y);
    }
});

var zoom = d3.behavior.zoom()
    .size([width, height])
    .on("zoom", zoomed);

// This projection is baked into the TopoJSON file,
// but is used here to compute the desired zoom translate.
var projection = d3.geo.mercator().translate([0, 0])



var canvas = d3.select("#map").append("canvas")
    .attr("width", width)
    .attr("height", height);

var context = canvas.node().getContext("2d");

var path = d3.geo.path()
    .projection(simplify)
    .context(context);

d3.json("http://weather-bell.com/res/nws_regions.topojson", function (error, json) {
    canvas.datum(topojson.mesh(topojson.presimplify(json)))
        .call(zoomTo(chesapeake, 0.05).event)
        .transition()
        .duration(5000)
        .each(jump);
});

function zoomTo(location, scale) {
    var point = projection(location);
    return zoom.translate([width / 2 - point[0] * scale, height / 2 - point[1] * scale])
        .scale(scale);
}

function zoomed(d) {
    translate = zoom.translate();
    scale = zoom.scale();
    visibleArea = 1 / scale / scale;
    invisibleArea = 200 * visibleArea;
    context.clearRect(0, 0, width, height);
    context.beginPath();
    path(d);
    context.stroke();
}

function jump() {
    var t = d3.select(this);
    (function repeat() {
        t = t.transition()
            .call(zoomTo(chesapeake, 100).event)
            .transition()
            .call(zoomTo(chesapeake, 0.05).event)
            .each("end", repeat);
    })();
}

我的猜测是我使用的topojson文件已经内置了投影,所以我应该在d3中使用空投影。 如果我根本不使用投影,地图会正确呈现:(http://jsfiddle.net/KQfrK/1/) - 但我无法简化缩放。

我觉得我错过了一些基本的东西...也许我只需要以某种方式旋转并放大我的第一个小提琴。

无论哪种方式,我都会感激一些帮助。一直在努力解决这个问题。

编辑:我使用QGIS保存geojson文件,其中包含&#34; EPSG:3857 - WGS 84 / Pseudo Mercator&#34;投影。 但是,当我使用topojson命令行实用程序将其转换为topojson,然后使用与上面相同的代码使用D3显示它时,我得到一个空白屏幕。

我应该在topojson命令行实用程序中指定投影吗?我试图这样做,但我收到一条错误消息:

topojson --projection EPSG:3857 E:\gitstore\public\res\nws.geojson -o E:\gitstore\public\res\nws.topojson --id-property NAME


[SyntaxError: Unexpected token :]

2 个答案:

答案 0 :(得分:0)

TopoJSON文件没有内置投影,当你没有指定一个投影时,你只是使用默认投影(这是albersUsa,见the documentation)。您可以通过调用d3.geo.projection()而无需参数来检索此投影。然后,您可以通过缩放等方式修改此投影。

答案 1 :(得分:0)

我使用墨卡托投影设置了这个fiddle,我根据this block采用了不同的放大和缩小方法,对我来说这是一种更简单的方法。我有一种感觉,在translate位的zoomTo函数中存在一个问题,但我可以确切地说它是什么。所以我用下面的代码替换了一个递归调用:

function clicked(k) {

    if (typeof k === 'undefined') k = 8;

    g.transition()
        .duration(5000)
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")scale(" + k + ")translate(" + -projection(chesapeake)[0] + "," + -projection(chesapeake)[1] + ")")
        .each("end", function () {
        (k === 8) ? k = 1 : k = 8;
        clicked(k);
    });