【问题标题】:D3.js map projections on a canvas imageD3.js 在画布图像上映射投影
【发布时间】:2015-02-10 07:42:34
【问题描述】:

我正在尝试获取画布元素的内容(实际上只是加载到画布上的图像)并使用 d3 将它们扭曲为不同的地图投影。所以我找到了一个这样做的例子(this other SO question)。

问题在于它不适用于每个投影。代码:

var height = 375,
    width = 750;

var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = width;
canvas.height = height;

var context = canvas.getContext('2d');

var projection = d3.geo.lagrange()
    .translate([width/2, height/2])
    .scale(100); //SET SCALE HERE

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

var image = new Image();
image.crossOrigin = 'anonymous';
image.src = 'http://i.imgur.com/zZkxbz7.png';
image.onload = function() {
    var dx = width,
        dy = height;

    context.drawImage(image, 0, 0, dx, dy);

    var sourceData = context.getImageData(0, 0, dx, dy).data,
        target = context.createImageData(dx, dy),
        targetData = target.data;

    for (var y = 0, i = -1; y < height; ++y) {
        for (var x = 0; x < width; ++x) {
            var p = projection.invert([x, y]),    //ERROR HERE
                λ = p[0],
                φ = p[1];
            if (λ > 180 || λ < -180 || φ > 90 || φ < -90) {
                i += 4;
                continue;
            }
            var q = ((90 - φ) / 180 * dy | 0) * dx + ((180 + λ) / 360 * dx | 0) << 2;
            targetData[++i] = sourceData[q];
            targetData[++i] = sourceData[++q];
            targetData[++i] = sourceData[++q];
            targetData[++i] = 255;
        }
    }

    context.clearRect(0, 0, width, height);
    context.putImageData(target, 0, 0);
}

在上面的例子中,如果我将投影的比例设置得太低(比如 80),那么变量 p(在 for 循环中)最终会变成 null。我不确定为什么会发生这种情况,我需要设置比例以使投影适合画布区域。

一个有效的 jsfiddle 示例:http://jsfiddle.net/vjnfyd8t/

【问题讨论】:

    标签: javascript d3.js d3.geo


    【解决方案1】:

    (这是一个有趣的问题)

    我不太明白这里发生了什么,但 FWIW,this is the implementation of the Lagrange invert() method。显然,在某些情况下它返回 null,大概是每当 x 或 y 超出某些范围时(x,y 是 pre-transformed here)。所以我猜你应该忽略空值(例如通过将输出像素设置为透明),最后你仍然可以获得适当的缩放地图。

    This is what I get 忽略 nulls(但用红色突出显示它们,以说明它发生的位置)

    if (!p) {
      targetData[++i] = 255;
      targetData[++i] = 0;
      targetData[++i] = 0;
      targetData[++i] = 255;
      continue;
    }
    

    如果将比例设置为 94,则红色条带会完全消失,这似乎是最合适的(至少在该比例下)。 这是你想要的吗?

    【讨论】:

    • 我花了很多时间试图弄清楚为什么它为空。从来没有想过只是忽略它。有趣的是,在图书馆支持的所有预测中,似乎只有 3 个(我可以说至少有 3 个)最终有空值。所以我很幸运(不幸?),因为我碰巧在我的测试中选择了 3 个中的一个。虽然现在仍然存在一些其他一些预测(例如 collignon)的奇怪之处,但您在这里回答了主要问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多