【问题标题】:D3.js canvas context fill wrongD3.js 画布上下文填充错误
【发布时间】:2018-01-25 08:07:51
【问题描述】:

我用 D3 制作地图,这是我的代码

d3.json('https://unpkg.com/world-atlas@1/world/110m.json', (error, topology) => {
        if (error) throw error;
        let width = map.offsetWidth,
            height = map.offsetHeight;

        let projection = d3.geoMercator().scale('200').translate([width / 2, height / 1.4]);

        let canvas = d3.select('.map').append('canvas')
            .attr('width', width)
            .attr('height', height);

        let context = canvas.node().getContext('2d'),
            path = d3.geoPath()
                .context(context)
                .projection(projection);

        context.fillStyle = '#d8d8d8';
        context.strokeStyle = 'black';

        context.beginPath();
        path(topojson.mesh(topology));
        context.fill();
        context.stroke()
    });

弄错canvas

有一些白色但应该是灰色的。 我不知道发生了什么,如果使用 svg 效果很好,但在这种情况下,我想使用画布。 谢谢。

【问题讨论】:

    标签: javascript d3.js topojson


    【解决方案1】:

    发生这种情况是因为您实际上并未绘制国家/地区。您正在围绕国家/地区绘制网格 - 这意味着您的要素不是国家/地区,而是边界(和海岸)段。

    通常在绘制国家时,每个要素都是一个完整的国家,并且填充路径会根据需要填充要素。因此,两国之间的每条边界都画了两次。 Topojson 对拓扑进行编码,将国家形状分解为线段,以便每个线段记录一次。 topojson 网格只生成这些线段。填充一条线本质上是通过将第一个点与最后一个点连接起来来创建一个多边形。在您的地图中,这在美国大陆的海岸上非常明显。

    尝试将topojson转换为geojson:

    topojson.feature(topology, topology.objects.features)
    

    在下面的 sn-p 中(使用您的代码):

    d3.json('https://unpkg.com/world-atlas@1/world/110m.json', (error, topology) => {
            if (error) throw error;
            let width = 960,
                height = 500;
    
            let projection = d3.geoMercator().scale('200').translate([width / 2, height / 1.4]);
    
            let canvas = d3.select('body').append('canvas')
                .attr('width', width)
                .attr('height', height);
    
            let context = canvas.node().getContext('2d'),
                path = d3.geoPath()
                    .context(context)
                    .projection(projection);
    
            context.fillStyle = '#d8d8d8';
            context.strokeStyle = 'black';
    
            context.beginPath();
            path(topojson.feature(topology, topology.objects.countries));
            context.fill();
            context.stroke()
        });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
    <script src="https://d3js.org/topojson.v2.min.js"></script>

    【讨论】: