D3.js画布上下文填写错误

时间:2017-08-17 03:25:47

标签: javascript d3.js topojson

我用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()
    });

并得到错误的画布enter image description here

有一些白色但应该是灰色的。 我不知道发生了什么,如果使用svg它可以很好地工作,但在这种情况下,我想使用canvas。 谢谢。

1 个答案:

答案 0 :(得分:1)

这是因为您实际上并未绘制国家/地区。您正在国家/地区绘制网格 - 这意味着您的要素不是国家/地区,而是边境(和海岸)细分。

通常在绘制国家/地区时,每个要素都是整个国家/地区,并且根据需要填充路径填充要素。因此,两个国家之间的每个边界都被抽两次。 Topojson对拓扑进行编码,拓扑将国家/地区形状划分为线段,以便每个段记录一次。 topojson网格只生成这些线段。填充线基本上通过链接第一个点和最后一个点来创建多边形。在你的地图中,这在美国大陆的海岸很明显。

尝试将topojson转换为geojson:

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

如下面的代码段(使用您的代码):

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>