使用D3.js转换画布上的地图投影

时间:2016-11-17 18:06:05

标签: javascript canvas d3.js d3.geo

我在做什么:

我有办法将图片上传到画布上。然后,我正在使用d3的地图投影,以允许选择不同的地图投影来将图像转换为。

问题:

转换仅在原始图像是等距矩形投影时才有效。例如,如果我上传一个equirectangular地球地图,然后告诉它将其转换为罗宾逊投影,它工作正常。如果我上传一个罗宾逊地图图像,然后尝试转换为一个equirectangular投影,它所做的就是用颜色填充透明数据(即它不起作用)。

我正在使用的代码:

function updateMapProjection(selection) {
    var projection = options[selection.selectedIndex].projection;
    //projection var will be something like 'd3.geo.robinson()`
    var projCanvas = document.getElementById('projectionCanvas');
    var projCtx = projCanvas.getContext('2d');
    projCtx.clearRect(0, 0, projCanvas.width, projCanvas.height);
    var tempImage = new Image();
    if (mapFile.indexOf("imgur.com") > -1) {
        tempImage.crossOrigin = "Anonymous";
    }
    tempImage.onload = function() {
        projCtx.drawImage(tempImage,0,0, projCanvas.width, projCanvas.height);

        var dx = projCanvas.width;
        var dy = projCanvas.height;

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

        for (var y = 0, i = -1; y < dy; ++y) {
            for (var x = 0; x < dx; ++x) {
                var p = projection.invert([x, y]);
                if (!p) {
                    targetData[++i] = 0;
                    targetData[++i] = 0;
                    targetData[++i] = 0;
                    targetData[++i] = 0;
                    continue;
                }
                var λ = 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;
            }
        }
        projCtx.clearRect(0, 0, dx, dy);
        projCtx.putImageData(target, 0, 0);
    }
    tempImage.src = mapFile;
    $(".loaderWrapper").hide();
}

有关工作示例,请参阅this jsfiddle。请注意,它不是实际转换地图,而是填充以前透明的白色区域。转换后的图片看起来像this

0 个答案:

没有答案