Как получить карту для точного отображения долготы и широты с помощью d3 - PullRequest
1 голос
/ 14 мая 2019

Я использую d3.js, чтобы попытаться отобразить координаты для файла данных CSV, который содержит идентификатор заказа, широту и долготу адреса, на который был отправлен заказ, и сумму, потраченную на заказ.Я попытался отобразить их линейно и попытался использовать логарифмическую шкалу, но точки графика все еще кажутся искаженными.Я пытался сделать так, чтобы он выглядел как карта США, на которую она немного похожа, но карта кажется искаженной / перекошенной.Я удостоверился, что долгота была установлена ​​к оси x, и что широта была установлена ​​для оси y.Радиусы кругов связаны с суммой, потраченной на заказы.Мне интересно, имеет ли это какое-то отношение к используемой шкале, но я впервые пытаюсь возиться с d3, поэтому любая помощь / совет будут оценены!

  var outerWidth  = 500;
  var outerHeight = 250;
  var margin = { left: -50, top: 0, right: -50, bottom: 0 };

  var xColumn = "longitude";
  var yColumn = "latitude";
  var rColumn = "total";
  var dollarPerPixel = 10;

  var innerWidth  = outerWidth  - margin.left - margin.right;
  var innerHeight = outerHeight - margin.top  - margin.bottom;

  var svg = d3.select("body").append("svg")
    .attr("width",  outerWidth)
    .attr("height", outerHeight);

  var g = svg.append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var xScale = d3.scale.log().range([0, innerWidth]);
  var yScale = d3.scale.log().range([innerHeight, 0]);
  var rScale = d3.scale.sqrt();

  function render(data){

    xScale.domain( d3.extent(data, function (d){ return d[xColumn]; }));
    yScale.domain( d3.extent(data, function (d){ return d[yColumn]; }));
    rScale.domain([0, d3.max(data, function (d){ return d[rColumn]; })]);

    // Compute the size of the biggest circle as a function of dollarPerPixel.
    var dollarMax = rScale.domain()[1];
    var rMin = 0;
    var rMax = Math.sqrt(dollarMax / (dollarPerPixel * Math.PI));
    rScale.range([rMin, rMax]);

    var circles = g.selectAll("circle").data(data);
    circles.enter().append("circle");
    circles
      .attr("cx", function (d){ return xScale(d[xColumn]); })
      .attr("cy", function (d){ return yScale(d[yColumn]); })
      .attr("r",  function (d){ return rScale(d[rColumn]); });
    circles.exit().remove();
  }

  function type(d){
    d.latitude   = +d.latitude;
    d.longitude  = +d.longitude;
    d.total = +d.total;
    return d;
  }

  d3.csv("data.csv", type, render);

1 Ответ

3 голосов
/ 14 мая 2019

Хотя шкалы могут показаться подходящим методом для построения географических точек: не используйте этот подход.

Вы теряете контроль над вращением проекции и не можете использовать нецилиндрическую проекцию (только не повернутые цилиндрические проекции могут строить широту и долготу независимо). Но также очень трудно выровнять объекты, расположенные по шкалам, с другими элементами карты, если они не используют тот же подход.

Вместо этого D3 имеет широкий диапазон встроенных проекций.

Проекции принимают пару [долгота, широта] и возвращают координату [x, y]. Широта и долгота должны быть в градусах, x и y в пикселях.

Для создания проекции вы можете использовать:

var projection = d3.geoMercator() // or geoAlbers, geoSupportedProjection, etc.

Чтобы использовать его, просто передайте ему координату:

projection([long,lat]) // [x,y]

В вашем случае это может выглядеть так (для cx, cy выглядит аналогично)

 .attr("cx", function(d) { return projection([d.long,d.lat])[0] })

Теперь эта проекция отцентрирована по умолчанию на 0,0 градусов и настроена для карты 960x500 пикселей. Но вы можете изменить масштаб, центр и вращение, например:

var projection = d3.geoMercator().center([-100,35]).scale(1000)

Для более полного ознакомления с методами проецирования вам следует обратиться к документации по d3-geo.

В вашем случае есть специальная составная проекция, охватывающая США, d3.geoAlbersUsa, в которой есть место для Гавайев и Аляски. Но из-за его составной природы менее гибок, хотя вы все еще можете масштабировать его. Масштаб по умолчанию предполагает карту 960x600 пикселей (при настройке большего масштаба карты карта распространяется по большей области).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...