Создание интерактивной карты потоков на JavaScript

Пошаговое руководство, показывающее, как создать интерактивную карту потока JS. Проиллюстрировано визуализацией данных по миграции в США.

Может показаться сложным создание интерактивной карты потока для Интернета с использованием JavaScript. Но это не так! Это простое в использовании руководство покажет вам, как без особых усилий создавать красивые карты потоков JS.

В эти трудные времена пандемии существует много путаницы и беспокойства по поводу иммиграционного статуса людей во всем мире. Я решил взглянуть на данные об иммиграции в США, где мигрантов больше, чем в любой другой стране мира. Здесь я исследую, откуда эти иммигранты, и представляю 15 стран, которые отправили наибольшее количество мигрантов в США в 2019 году.

Карта потоков кажется идеальным способом продемонстрировать приток мигрантов в Соединенные Штаты из разных стран. Прежде чем идти дальше, позвольте мне дать вам краткое представление о карте потока и ее использовании.

Что такое карта потока?

Карты потоков географически визуализируют перемещение объектов – например, людей или товаров из одного места в другое и их количество.

Карта потока – это тип карты-соединителя, который создается путем соединения точек, размещенных на карте, прямыми или изогнутыми линиями со стрелкой или маркером, указывающим направление потока. Как правило, величина потока представлена ​​толщиной линии.

Начальная и конечная точки для соединителей на этих картах определяются параметрами широты и долготы, поэтому необходимо установить их для каждого соединителя. Обратите внимание, что сначала необходимо определить широту, а затем долготу для каждой точки.

Например, вот карта потока, которую я создам к концу этого урока.

Создание карты потока с помощью JavaScript

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

В этом уроке я использую AnyChart . Здесь он выглядит наиболее подходящим с опцией готовой схемы потока и подробной документацией для понимания процесса.

Карта потока немного сложнее, чем базовая диаграмма, такая как столбчатая или круговая диаграмма, но я проведу вас по строкам кода, чтобы облегчить понимание. Некоторые базовые знания о HTML и JavaScript помогут вам понять быстрее, но, тем не менее, это не так уж сложно. Посмотрите, как вы можете создать красивую интерактивную карту потока JavaScript за 4 простых шага.

Создание HTML-страницы

Первый шаг – создать пустую HTML-страницу, которая будет содержать интерактивную карту потока. Добавьте div на эту страницу элемент с уникальным идентификатором, ссылка на который будет указана позже.

Я установил ширину и высоту div на 100%, чтобы карта отображалась на всем экране. Это может быть изменено в зависимости от требований и предпочтений.

<html>
  <head>
    <title>JavaScript Flow Map</title>
    <style type="text/css">      
        html, body, #container { 
            width: 100%; height: 100%; margin: 0; padding: 0; 
        } 
    </style>
  </head>
  <body>
    <div id="container"></div>
  </body>
</html>

Добавление необходимых скриптов

Чтобы использовать библиотеку диаграмм для построения визуализации данных, вам необходимо связать соответствующие сценарии JS библиотеки, которую вы используете. Все эти файлы сценария включены в HTML-страницу.

Для создания карты потока JS я добавлю модули AnyChart ‘ core ‘ и ‘ geo maps ‘.
Поскольку карта всего мира, я связываю файл, содержащий геоданные мира, из коллекции карт библиотеки, также доступной на ее CDN .

Кроме того, я воспользуюсь другой библиотекой JavaScript – Proj4js, которая, занимается нанесением координат в соответствующих географических областях.

<html>
  <head>
    <title>JavaScript Flow Map</title>
    
    <script src="https://cdn.anychart.com/releases/8.10.0/js/anychart-core.min.js"></script>
    <script src="https://cdn.anychart.com/releases/8.10.0/js/anychart-map.min.js"> </script>

    <script src="https://cdn.anychart.com/geodata/latest/custom/world/world.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.15/proj4.js"></script>

    <script src="https://cdn.anychart.com/releases/8.10.0/js/anychart-data-adapter.min.js"></script>

    <style type="text/css">      
        html, body, #container { 
            width: 100%; height: 100%; margin: 0; padding: 0; 
        } 
    </style>
  </head>
  <body>  
    <div id="container"></div>
    <script>
      // All the code for the JS flow map will come here
    </script>
  </body>
</html>

Подключение данных

Для карты данные должны иметь координаты широты и долготы, а также другую информацию, которая будет отображаться. Я создал набор данных, сопоставив иммиграционную информацию из Википедии и добавив координаты с сайта под названием Latlong .

Для карты потока мне нужны широта и долгота исходной страны, а также назначения. Здесь страной назначения для всех точек данных является США. Чтобы узнать, как выглядит набор данных, вы можете найти файл здесь .

Чтобы загрузить файл данных, я включу модуль Data Adapter AnyChart в <head> раздел HTML-страницы.

Написание JS-кода для рисования карты потока

Прежде всего, я заключу весь код в функцию anychart.onDocumentReady (), которая обеспечит полную загрузку страницы до того, как что-либо будет выполнено. Затем я загружу данные с помощью функции anychart.data.loadJsonFile ().

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

anychart.onDocumentReady(function () {
  anychart.data.loadJsonFile(    'https://gist.githubusercontent.com/shacheeswadia/a20ba5b62cef306ccc1a8e8857e5316a/raw/0337b16fa8dc4de97263bc0a4ededf935a529c35/migration-data.json',
    function (data) {
      // Creates map chart
      var map = anychart.connector();

      // Sets settings for map chart
      map.geoData('anychart.maps.world');

      // Darkens all the regions
      map
        .unboundRegions()
        .enabled(true)
        .fill('#E1E1E1')
        .stroke('#D2D2D2');
    })
  });

Я добавляю заголовок к диаграмме и разрешаю перекрытие, чтобы все точки данных вместе с их метками были видны на карте, даже если они перекрываются.

// Sets title for map chart 
map
  .title('Migrations to the USA from the top 15 countries');

// Display all labels even if there is an overlap
map. 
  overlapMode("allow-overlap");

Теперь переходим к основной части создания серии соединителей, которые будут представлять различные соединения.

Для этого я создаю вспомогательную функцию с данными в качестве параметра. В этой функции я создаю серию, которая сформирует соединительные линии, и добавлю маркеры стрелок в позиции 100%, которая является пунктом назначения, поскольку наш поток идет из различных стран-источников в страну назначения – США.

Затем я добавляю метки, отображающие названия стран происхождения.

// Helper function to create several series
var createSeries = function (data) {

  // Creates connector series and customizes them
  var connectorSeries = map
    .connector(data);

  connectorSeries
    .markers()
    .position('100%')
    .size(10);

  // Sets labels for the source countries
  connectorSeries
    .labels()
    .enabled(true)
    .format(function () {
    return this.getData('from');
    });
};

Теперь я устанавливаю данные и вызываю созданную мной функцию с этим набором данных в качестве аргумента. Заключительные шаги – установка контейнера для ссылки на ранее добавленный div и рисование карты.

// Creates Dataset from the data
var dataSet = anychart.data.set(data).mapAs();

createSeries(dataSet);

// Sets container id for the chart
map.container('container');

// Initiates chart drawing
map.draw();

И вот! Создана красивая, функциональная карта потока на основе JavaScript! Не так ли сложно было создать такую ​​интерактивную визуализацию данных?

исходная карта

Настройка карты потока JS

Существующая карта потоков, только что построенная с использованием JavaScript, является хорошим представлением, показывающим, откуда происходит большинство мигрантов. Но количество иммигрантов из каждой страны не отображается. Итак, я настрою карту, чтобы показать это и сделать карту более информативной, добавив дополнительный код. Я также улучшу визуальную эстетику и внесу некоторые другие незначительные изменения.

A. Установка цвета и размера соединителей вместе с легендой

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

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

Затем я добавляю название и цвет к серии соединителей, а также добавляю настройки для наведения курсора на линию и маркер.

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

Поскольку серия соединителей имеет разные цвета в зависимости от данных, я добавляю цветную легенду.

Не расстраивайтесь, если все это звучит сложно. Если вы посмотрите на код и комментарии вместе с каждым фрагментом, это станет более понятным.

// Helper function to create several series
var createSeries = function (name, data, color) {

  // Creates connector series for destinations and customizes them
  var connectorSeries = map
  	.connector(data)
  	.name(name)
  	.fill(color)
  	.stroke({
  		color: color,
  		thickness: 2
    });
  
  // Changes color to indicate the hovered line
  connectorSeries
    .hovered()
    .stroke('1.5 #212121')
    .fill('#212121');

  // Settings for the arrow marker
  connectorSeries
    .markers()
    .position('100%')
    .fill(color)
    .stroke({
      color: color
    })
    .size(8);

  // Settings for the hovered marker
  connectorSeries
    .hovered()
    .markers()
    .position('100%')
    .size(10)
    .fill('#212121')
    .stroke('2 #455a64');

  // Sets labels for the source countries
  connectorSeries
    .labels()
    .enabled(true)
    .format(function () {
      return this.getData('from');
    });

  // Sets the thickness of the line based on the series
  if (name === 'More than 50,000') {
    connectorSeries.startSize(5).endSize(2);
  } else if (name === '40,000 to 50,000') {
    connectorSeries.startSize(3.5).endSize(1.5);
  } else if (name === '20,000 to 40,000') {
    connectorSeries.startSize(3).endSize(1);
  } else if (name === '16,000 to 20,000') {
    connectorSeries.startSize(2).endSize(0.5);
  } else {
    connectorSeries.startSize(1).endSize(0);
  }

  // Sets settings for legend items
  connectorSeries
    .legendItem()
    .iconType('square')
    .iconFill(color)
    .iconStroke(false);
  };

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

// Helper function to bind data field to the local var.
function filterFunction(val1, val2) {
  if (val2) {
    return function (fieldVal) {
      return val1 <= fieldVal && fieldVal < val2;
    };
  }
  return function (fieldVal) {
    return val1 <= fieldVal;
  };
}

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

// Creates 6 series, filtering the data by the amount of migration numbers
createSeries(
  'Less than 16,000',
  dataSet.filter('total', filterFunction(0, 16000)),
  '#fed693'
);
createSeries(
  '16,000 to 20,000',
  dataSet.filter('total', filterFunction(16000, 20000)),
  '#f5ad52'
);
createSeries(
  '20,000 to 40,000',
  dataSet.filter('total', filterFunction(20000, 40000)),
  '#3fb8c5'
);
createSeries(
  '40,000 to 50,000',
   dataSet.filter('total', filterFunction(40000, 50000)),
   '#1792c0'
);
createSeries(
   'More than 50,000',
   dataSet.filter('total', filterFunction(50000, 1000000)),
   '#1c5eaa'
);

Поскольку я добавил легенду, я включаю ее для карты и добавляю заголовок к легенде.

// Turns on the legend for the sample
map
  .legend()
  .enabled(true)
  .position('center')
  .padding([20, 0, 20, 0])
  .fontSize(10);

map
  .legend()
  .title()
  .enabled(true)
  .fontSize(13)
  .padding([0, 0, 5, 0])
  .text('Number of Migrants (in the year 2019)');

Обратите внимание, что легенда интерактивна. Таким образом, вы можете навести курсор на каждый элемент легенды, и соответствующая группа серий будет выделена. Вы также можете щелкнуть элементы легенды, чтобы добавить или удалить эту конкретную группу серий. Это все встроенные возможности библиотеки диаграмм JS.
Взгляните на эту промежуточную настроенную версию карты потока здесь и проверьте весь код на CodePen .

Б. Улучшение информации во всплывающей подсказке

Подсказка по умолчанию для карты потока JavaScript показывает широту и долготу источника и пункта назначения. Эта информация нам не нужна. Итак, я настраиваю всплывающую подсказку, чтобы отображать название страны и общее количество мигрантов из этой страны.

Я использую HTML для всплывающей подсказки, которая позволяет мне форматировать текст. Это делает всплывающую подсказку более информативной и привлекательной.

// sets tooltip setting for the series
connectorSeries
  .tooltip()
  .useHtml(true)
  .format(function () {
    return (
    '<h4 style="font-size:14px; font-weight:400; margin: 0.25rem 0;">From:<b> ' + this.getData('from') + '</b></h4>' + '<h4 style="font-size:14px; font-weight:400; margin: 0.25rem 0;">Total Migrants::<b>' + this.getData('total').toLocaleString() + '</b></h4>'
    );
  });

C. Улучшение заголовка и ярлыков

В конце концов, я вношу несколько простых модификаций, чтобы улучшить эстетику карты и добавить некоторые идеи в заголовок.

Я форматирую заголовок и снова добавляю подзаголовок с помощью HTML, чтобы сделать стиль текста настраиваемым.

// Sets title for map chart and customizes it
map
  .title()
  .enabled(true)
  .useHtml(true)
  .padding([0, 0, 40, 0])
  .text(
    '<span style="color:#212121;">Migrations to the USA from the top 15 countries</span><br/>' +
    '<span style="font-size: 14px;">Majority of the migrants come from Mexico, Asia and South America</span>'
  );

Наконец, я сдвигаю легенду карты вниз и затемняю цвета меток, чтобы сделать их более заметными.

map
  .legend()
  .position('bottom')

Выполнено! Прекрасная интерактивная карта потока JS готова проиллюстрировать данные об иммиграции в США.

final-map-with-tooltip.PNG

Весь код окончательной готовой версии находится на CodePen .

Заключение

Создание интерактивных карт с помощью JavaScript может быть трудным, но использование библиотек диаграмм JS значительно упрощает и ускоряет создание таких визуализаций. В AnyChart доступно множество типов диаграмм, которые вы можете проверить здесь или заглянуть в другие библиотеки диаграмм JavaScript, чтобы узнать о них больше.
Я надеюсь, что этот урок определил создание карты потока для вас и вдохновил вас исследовать больше диаграмм с библиотеками JavaScript. Независимо от того, являетесь ли вы коренным жителем или мигрантом, дом – это место, где все счастливее, а библиотеки диаграмм JS – там, где создание диаграмм проще!

Ответить