我创建了此地图( PLUNKER )。

它用nuts0(国家)表示欧洲,如果右键单击一个国家,该县将被缩放并显示其地区(nuts2)。

一段代码:

var projectionCurrent = d3.geoMercator()
    .scale(1)
    .translate([width / 2, height / 2]);

var projectionBase = d3.geoMercator()
    .scale(1)
    .translate([width / 2, height / 2]);

var path = d3.geoPath().projection(projectionCurrent);

var map = d3.select('#container-map');

var mapSvg = map.append('svg')
    .attr('id', 'container-map-svg')
    .attr('width', width)
    .attr('height', height);

var mapSvgG = mapSvg.append('g');

function makeMap(data) {
    var nuts0 = data[0];
    var nuts2 = data[1];
    var countries = topojson.feature(nuts0, nuts0.objects.nuts0);
    var regions = topojson.feature(nuts2, nuts2.objects.nuts2);
    projectionBase.fitSize([width, height], countries);
    projectionCurrent.fitSize([width, height], countries);

    mapSvgG.selectAll('path')
        .data(countries.features)
        .enter()
        .append('path')
        .attr('class', 'country')
        .attr('fill', 'steelblue')
        .style('stroke', 'white')
        .style('stroke-width', 1)
        .attr('d', path)
        .attr('id', function(c) {
            return 'country' + c.properties.nuts_id;
        })

        .on('mouseover', function(c) {
            d3.select(this)
                .attr('fill', 'white')
                .raise();
        })
        .on('mouseout', function(c) {
            d3.select(this)
                .attr('fill', 'steelblue');
        })
        .on('contextmenu', function(d, i) {
            d3.event.preventDefault();
            d3.selectAll('.region').remove();

            var features = regions.features.filter(function(feature) {
                return feature.properties.nuts_id.substring(0, 2) == d.properties.nuts_id;
            });

            mapSvg.selectAll(null)
                .data(features)
                .enter()
                .append('path')
                .attr('class', 'region')
                .attr('fill', 'tomato')
                .style('stroke', 'white')
                .style('stroke-width', 1)
                .attr('d', path)
                .attr('id', function(r) {
                    return 'region' + r.properties.nuts_id;
                })
                .on('mouseover', function(r) {
                    d3.select(this)
                        .attr('fill', 'white')
                        .raise();
                })
                .on('mouseout', function(r) {
                    d3.select(this)
                        .attr('fill', 'tomato');
                })
                .on('contextmenu', function(r, i) {
                    d3.event.preventDefault();
                    zoomCountries(projectionCurrent, projectionBase);
                    d3.selectAll('.region').remove();
                })
                .raise();

                var featureCollection = { 'type': 'FeatureCollection', 'features': features }
                var projectionEnd = d3.geoMercator();
                zoomCountries(projectionCurrent, projectionEnd.fitExtent([[50, 50], [width-50, height-50]], featureCollection));

            });

}

问题在于,如果右键单击某个国家/地区,则会看到这些区域,而区域附近则存在一些缺陷。

我认为图像可以更好地说明问题:

d3.js - 重叠 map 之间的不精确度-LMLPHP

在这种情况下,我选择了瑞士。
您可以看到区域(红色),邻国(蓝色)和瑞士国家的路径为白色。

我认为问题在于我使用的json文件不是很精确。

这些是原始文件:
  • nuts0
  • nuts2

  • 然后,我使用mapshaper对其进行了简化(使用相同的设置)。
    特别是:
  • 我已使用Visvalingam/weighted area上的0.70%算法简化了json文件。
  • 我使用控制台执行一些命令,例如:filter 'name != "Iceland"'filter 'name != "Turkey"'(显然,对于nuts2,我消除了冰岛和土耳其,消除了所有区域)
  • 我将文件导出为topoJson。
  • 最后,我使用Qgis删除了一些岛,另存为geoJson(我按照以下步骤操作:firstsecond)
  • 在Mapshaper中导入,并作为topoJson导出。

  • 生成的文件是nuts0topojson3.jsonnuts2topojson3.json(我用来创建地图)。

    我希望这个问题不那么明显。我能怎么做?

    最佳答案

    您的问题是由于简化-您正在极大地简化多边形,区域层和国家/地区层具有不同的面积权重,因此简化过程会不同地改变每一层。

    简化不同层始终是一个问题。这些文件并非以这种差异开头,因此您可以使用未简化的文件,但这太详细了。

    而是对国家和地区使用简化的区域层。每个区域都有一个结合了国家代码和数字的标识符(两个字母的国家代码,后跟一些数字)。我使用以下方法创建了一个新属性,该属性在区域文件中标识国家/地区:

    nuts2.objects.nuts2.geometries.forEach(function(n) {
      n.properties.country = n.properties.id.substring(0,2);
    })
    

    现在,我们可以将修改后的topojson放到mapshaper中,然后在控制台中应用溶解(溶解也可以在QGis或任何其他GIS平台中轻松完成)。在mapshaper中:
  • 导入topojson
  • 打开控制台
  • 类型dissolve country
  • 将溶解层导出为新的topojson文件

  • 现在,有一件事是,由于我们使用了nuts2,因此此新文件中不存在objects.nuts0,因此为了清楚起见,我们可以将其修改为nuts0。我们也没有国家/地区的所有属性,我们只有两位数字的国家/地区代码。这需要一些代码调整才能访问country属性,而不是原始国家/地区层中存在的ID。

    由于我们有一个区域层和一个国家层,它们共享来自同一文件(区域层)的相同边界,因此,我们不会出现空白或重叠的问题。

    这是一个基于您的plunkr的demonstration block。 (我急于更改了topojson文件名)。

    这可以进一步优化,例如,如果我们将区域和国家/地区合并到同一个topojson中,则只需要加载一次几何图形(并且由于国家/地区与区域共享弧,因此要加载的数据更少)。也可以使用不同的数据准备或GIS叠加来将每个国家的国家属性保留在已分解文件中。

    关于d3.js - 重叠 map 之间的不精确度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49779429/

    10-11 04:45