d3.js мир топожсон v4

Я пытаюсь сделать карту мира похожей на карту США, представленную здесь (карта США ), но я сталкиваюсь с некоторыми проблемами. В настоящее время это то, что у меня есть для моего кода карты мира:

<!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>

Я считаю, что неправильно масштабировал и неправильно делал проекцию на карту. Если у кого-то есть какие-либо комментарии о том, как я это сделал, пожалуйста, дайте мне знать.


person ans    schedule 10.07.2017    source источник


Ответы (1)


Американский json, на который вы ссылаетесь, представляет собой специальный json-файл — ему не нужно использовать проекцию. Ваша переменная path использует нулевую проекцию (проекцию по умолчанию), преобразуя координату в геоджсоне (в которую преобразуется топоджсон) в значения пикселей без преобразования.

Этот файл мог быть создан, чтобы позволить более простым блокам показывать функциональность d3, пропуская детали проекции, но в любом случае он относительно уникален из-за того, как он проецируется.

Каждая вершина в этом JSON-файле США была преобразована из пары широта/долгота, представляющей точку на трехмерной земле, в декартову координату x,y, представляющую плоскость шириной 960 и высотой 500 (ширина и высота вид блока по умолчанию). Ваши мировые данные по-прежнему содержат пары широты и долготы, и поэтому необходимо использовать проекцию.

Выдача того, что ваши данные не проецируются, заключается в том, что они перевернуты, что получается при преобразовании данных широты и долготы в пиксельные координаты в svg без преобразования, определяющего проекцию. Северный полюс находится на 90 градусах северной широты, экватор на 0 градусах. При работе с SVG координата y, равная нулю, будет вверху экрана, а координата y, равная 90, будет на 90 пикселей ниже. Таким образом, северный полюс будет ниже экватора при преобразовании точек широты и долготы в точки x, y svg без преобразования. Кроме того, западное и южное полушария имеют отрицательные значения x и/или y, поэтому они не появятся в вашем svg без преобразования. Вот почему на карте отображаются только точки к востоку от нулевого меридиана и к северу от экватора.

Как это исправить? Вам нужно проецировать свои данные. Вы можете использовать любую проекцию, я буду использовать проекцию Меркатора, поскольку она, вероятно, более узнаваема, чем другие (несмотря на серьезные проблемы с искажениями вблизи полюсов):

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

Вот и все (см. здесь).

Для справки, параметры проекции Меркатора по умолчанию предназначены для отображения земли на 960 пикселей, если вы хотите сфокусироваться на определенной области или показать карту с другим размером (масштабом), вам нужно будет установить параметры проекции .

person Andrew Reid    schedule 10.07.2017