【问题标题】:d3.js world topojson v4d3.js 世界 topojson v4
【发布时间】:2017-12-14 18:04:45
【问题描述】:

我正在尝试让世界地图显示类似于此处提供的美国地图 (U.S. map),但我遇到了一些问题。目前,这就是我迄今为止的世界地图代码:

<!DOCTYPE html>
<style>

</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>

var svg = d3.select("svg");

var path = d3.geoPath();

d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function(error, world) 
{
    if (error) throw error;

    svg.append("g")
        .selectAll("path")
        .data(topojson.feature(world, world.objects.countries).features)
        .enter().append("path")
          .attr("d", path);

});

</script>

但是,它显示的地图只占据了我窗口的左上角,看起来不正确。 目前我对我可能做错了什么有点困惑。如果有人有任何见解,我将不胜感激。

谢谢。

编辑:我实际上能够使用此处提供的代码来使用它

<!DOCTYPE html>
<style>

    .countries :hover
    {
        fill: red;
    }

    .country-borders
    {
        fill:   none;
        stroke: #FFF;
        stroke-width: 0.5px;
        stroke-linejoin: round;
        stroke-linecap: round;
        cursor: pointer;

    }

</style>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
var format = d3.format(",");


var margin = {top: 0, right: 0, bottom: 0, left: 0},
            width = 1200 - margin.left - margin.right,
            height = 900 - margin.top - margin.bottom;


var path = d3.geoPath();

var svg = d3.select("body")
            .append("svg")
            .attr("width", width)
            .attr("height", height)
            .append('g')
            .attr('class', 'map');

var projection = d3.geoMercator()
                   .scale(170)
                  .translate( [width / 2, height / 1.5]);

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


d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function( error, world ) 
{
    svg.append("g")
      .attr("class", "countries")
    .selectAll("path")
      .data(topojson.feature( world, world.objects.countries ).features )
    .enter().append("path")
      .attr("d", path);


    svg.append("path")
        .attr( "class", "country-borders" )
        .attr("d", path(topojson.mesh( world, world.objects.countries, function( a, b) 
        {
            return a !== b;
        })));
});

</script>
</body>
</html>

我相信我的缩放比例错误并且没有正确地投影到地图上。如果有人有任何关于我是如何做到的,请告诉我。

【问题讨论】:

    标签: d3.js svg topojson


    【解决方案1】:

    您引用的美国 json 是一个特殊的 json 文件 - 它不需要使用投影。您的 path 变量使用空投影(默认投影),将 geojson 中的坐标(topojson 转换为该坐标)转换为像素值而无需转换。

    创建此文件可能是为了让更简单的块通过跳过投影细节来显示 d3 功能,但无论如何它是相对独特的,因为它是如何投影的。

    美国 json 文件中的每个顶点都已从表示 3 维地球上一个点的纬度/经度对转换为表示宽度为 960 和高度为 500 的平面的笛卡尔 x,y 坐标(宽度和块的默认视图的高度)。您的世界数据仍然包含经纬度对,因此需要使用投影。

    您的数据未投影的一个缺点是它是颠倒的,这会导致将纬度经度数据转换为 svg 中的像素坐标而没有定义投影的变换。北极在北纬90度,赤道在0度。使用 SVG 时,y 坐标为零将位于屏幕顶部,y 坐标为 90 将向下 90 个像素。因此,当将纬度经度点转换为 x,y svg 点而不进行转换时,北极将位于赤道下方。此外,西半球和南半球的 x 和/或 y 值为负,因此如果不进行变换,它们将不会出现在您的 svg 中。这就是为什么您在地图上只能看到本初子午线以东和赤道以北的点。

    如何解决这个问题?您需要投影您的数据。您可以使用任何一种投影,我将使用墨卡托投影,因为它可能比其他投影更容易识别(尽管两极附近存在严重失真问题):

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

    就是这样 (see here)。

    作为参考,墨卡托投影的默认参数旨在以 960 像素显示地球,如果您想专注于特定区域或以不同的大小(比例)显示地图,则需要设置投影参数。

    【讨论】:

      猜你喜欢
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 2021-06-11
      • 1970-01-01
      • 2014-09-23
      • 1970-01-01
      • 2018-04-24
      相关资源
      最近更新 更多