Ищете карту мира с определенной проекцией в d3js - PullRequest
0 голосов
/ 17 февраля 2019

Я играл с картами d3js (v5) , я пытаюсь сгенерировать эту карту (скриншот взят со случайного сайта), Для моего конкретного случая нетнужно представить Антарктиду .

enter image description here

Я прочитал документацию здесь: https://github.com/d3/d3-geo#projections, и следовал инструкциям и использовал geoMercator,получил эту плоскую карту, которая по некоторым причинам получает отсечение на верхнем севере .

enter image description here

Какой правильный подход для получениямакет первой карты?есть предложения?

1 Ответ

0 голосов
/ 18 февраля 2019

Проекция, на которую вы смотрите - это проекция Меркатора .

При d3.geoMercator() значение шкалы получается из окружности цилиндра, который образует проекционную поверхность.Значение масштаба - это количество пикселей на радиан.Значение по умолчанию предполагает растяжение 360 градусов цилиндра на 960 пикселей: 960/Math.PI/2.

Для вертикальных угловых расстояний такого масштабного коэффициента не существует, так как человек перемещается на крайние долготы, угловое расстояние между точками все больше преувеличивается, так что полюса будут на ± бесконечности по оси y.Из-за этого Меркатора, особенно веб-Меркатора, часто усечены на ± 85 градусов.С экстентами [-180,85] и [180, -85] Mercator имеет квадратную форму.

Этот предел включен в d3-geoMercator, который "определяет стандартную проекцию.clipExtent, так что мирпроецируется на квадрат, обрезанный примерно до ± 85 ° широты. ( docs ) "

Это означает, что если мы хотим показать полный экстент d3-geoMercator, через 960 x960 пикселей, мы можем использовать:

d3.geoMercator()
 .scale(960/Math.PI/2)  // 960 pixels over 2 π radians
 .translate([480,480])  // the center of the SVG/canvas

Что дает нам:

enter image description here

Центр по умолчанию d3-geoMercator равен [0 °, 0 °], поэтому, если мы хотим, чтобы [0 °, 0 °] находился в середине SVG / холста, мы переводим центр так, чтобы он был посередине, с переводом [width/2,height/2]

Теперь, когда мы показываем весь мир, мы можем уточнить, чтобы показать только ту часть, которую мы хотим.Самый простой способ - просто отсечь пиксели снизу svg / canvas.Используя приведенный выше код с высотой холста / svg 700 пикселей (и сохраняя ширину 960 пикселей, используя тот же масштаб и перевод), я получаю:

enter image description here

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

Итак, SVG / Canvas шириной 960, высотой 700, с масштабом проекции 960 / Math.PI / 2 и переводом [480,480], кажется, в порядке.Эти значения будут масштабироваться вместе для разных размеров порта просмотра.

С картами часто бывает много глаз, чтобы получить желаемый визуальный эффект, настройка projection.translate() или projection.center() может помочь сместить карту в нужное место.Но мы можем сделать это вычислительно.Я расскажу об одном методе здесь, используя projection.fitSize() (хотя это не решит требуемое соотношение сторон без дополнительных шагов).

Project.fitSize([width,height],geojson) принимает массив, определяющий размеры SVG / холста и объекта геоджон, и настраивает масштаб проекции и переводит значения так, чтобы объект геоджон содержался в SVG / холсте.Элемент geojson может быть ограничивающей рамкой той части мира, которую вы хотите показать, поэтому вы можете использовать:

projection.fitSize([width,height], {
    type: "Polygon",
    coordinates: [[ 
      [-179.999,84] , 
      [-179.999,-57] , 
      [179.999,-57] , 
      [179.999,84], 
      [-179.999,84] 
     ]]
   })

Где ~ 84 градуса северной широты - северный конец Гренландии, а ~ 56 градусов южной широты.примерно верхушка Южной Америки.Это обеспечит видимость всей части мира, которую вы хотите увидеть.Однако, как отмечено выше, это не учитывает аспект, поэтому, если вы ограничите вышеуказанный экстент квадратными измерениями, вы все равно будете показывать полный экстент Меркатора.

...