首页 > 解决方案 > 将 SVG 矢量平铺地图转换为使用 Canvas 时出现问题

问题描述

我正在制作一张加拿大选举投票区的可视化地图。我设法在这里获得了一个有效的 SVG 版本。

然而,性能很差,所以我想我会改为在 Canvas 上绘图。我把我认为是直接转换的东西放在一起:

class VectorMap {

constructor(map_file, element_id) {
    this.map_file = map_file;
    this.root = $(`#${element_id}`)[0];
    this.init_map();
}

init_map() {
    var root_rect = this.root.getBoundingClientRect();
    this.width = root_rect.width;
    this.height = 720; 

    this.zoom = d3.zoom()
        .on('zoom', _ => this.onZoom(d3.event.transform));

    var canvas = d3.select(this.root).append('canvas')
        .attr('width', this.width)
        .attr('height', this.height)
        .call(this.zoom);
    this.context = canvas.node().getContext('2d');

    this.projection = d3.geoMercator()
        .scale(1 / 2 / Math.PI)
        .translate([0, 0]);

    this.path = d3.geoPath()
        .projection(this.projection)
        .context(this.context);

    this.onZoom(d3.zoomIdentity);
}

onZoom(transform) {       
    var tiler = d3.tile()
        .size([this.width, this.height])
        .scale(transform.k)
        .translate([transform.x, transform.y])

    //init drawing parameters
    this.context.save();
    this.context.fillStyle = 'gray';
    this.context.strokeStyle = 'red';
    //this.context.lineWidth = 1 / transform.k;
    this.context.setTransform(1, 0, 0, 1, 0, 0);
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.scale(transform.k, transform.k);
    this.context.translate(transform.x, transform.y);

    var tiles = tiler();
    tiles.forEach(tile => {
        console.log(tile);
        var zoom = tile[2];
        var x = tile[0];
        var y = tile[1];
        if (zoom > 10) {
            // since these are vector tiles we can just overzoom the z10 ones
            x = Math.floor(x / Math.pow(2, zoom - 10));
            y = Math.floor(y / Math.pow(2, zoom - 10));
            zoom = 10;
        }
        d3.json(`/maps/${zoom}/${x}/${y}/`)
            .then(function(json) {
                json.features.forEach(feature => {
                    this.context.beginPath();
                    path(feature);
                    this.context.closePath();
                    this.context.stroke();
                    this.context.fill();
                });
            });
    });
    this.context.restore();
}

但它什么也没画。显然 SVG 和 Canvas 之间发生了一些变化,但我不确定是什么。只是绘制矩形似乎有效,所以我假设这是画布路径生成器的问题。

标签: javascriptd3.jssvghtml5-canvasvector-tiles

解决方案


推荐阅读