days to give it a try before you buy! Download now. The best deals on licenses are coming soon Download now. The best deals on licenses are coming soon

Интерактивная карта Webix GeoChart

Новый Webix 5.0 включает в себя виджет JavaScript GeoChart, созданный с помощью Google Maps API. GeoChart — это изящный сервис для создания картографических диаграмм c отображением данных стран и регионов. Я покажу вам, как использовать основные функции виджета для создания интерактивной карты мира. Если вы еще не знакомы с виджетом, я надеюсь, что GeoChart станет вашим верным другом. Если вы уже любите GeoChart так же сильно, как я, вы, вероятно, получите лучшее представление о том, как можно с ним взаимодействовать.

Webix with Google GeoChart

Базовый GeoChart для отображения данных

Во-первых, давайте покажем данные в режиме readonly (только для чтения). Макет приложения будет иметь три панели: 

  • карта 
  • боковая панель с элементами управления 
  • нижняя панель с записями данных 

initial visualization GeoChart

Прежде чем инициализировать GeoChart, не забудьте получить свой личный ключ

Несколько строк кода добавят GeoChart в приложение. Вот простая карта с небольшими данными: 

webix.ui({
    view:"geochart",
    id:"map",
    // provide your own Google API key
    // https://developers.google.com/maps/documentation/javascript/get-api-key
    key:"AIzaSyAi0oVNVO-e603aUY8SILdD4v9bVBkmiTg",
    data:[
{id:1, country:'Germany', code:"DE", area:357,  population:83 },
      {id:2, country:'United States', code:"US", area:9834, population:323 },
      {id:3, country:'Brazil', code:"BR", area:8516, population:207 },
      //...
    ]
});

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

var mapdata = new webix.DataCollection({data:[
  {id:1, country:'Germany', code:"DE", area:357,  population:83 },
  {id:2, country:'United States', code:"US", area:9834, population:323 },
  {id:3, country:'Brazil', code:"BR", area:8516, population:207 },
//...

Обратите внимание, что GeoChart не имеет собственного источника данных, так как они берутся из DataCollection:

var map = {
    view:"geochart",
    id:"map",
    // provide your own Google API key
    // https://developers.google.com/maps/documentation/javascript/get-api-key
    key:"AIzaSyAi0oVNVO-e603aUY8SILdD4v9bVBkmiTg"
};

Для записей данных я создам JS DataTable

var grid = {
  view:"datatable", id:"grid", autoheight:true,
  scroll:false, autoConfig:true
}

Вот макет:

webix.ui({
  cols:[
    form,
    { view:"scrollview", body:{
      type:"clean", rows:[
        map,
        grid
      ]
    }}
  ]
});

form на данный момент — это просто шаблон, который резервирует место для элементов управления на боковой панели. Карта и DataTable заключены в представление scrollview, чтобы адаптировать демонстрацию под изменения размера. Для этой же цели я отключила прокрутку сетки по умолчанию.

Чтобы синхронизировать GeoChart и DataTable с DataCollection, вызываем sync:

$$("map").data.sync(mapdata);
$$("grid").data.sync(mapdata);

Демо>>

Режимы GeoChart

GeoChart имеет множество опций, которые могут изменить внешний вид карты. Например, существует три способа пометить области со связанными данными:

  • regions — цветовые области карты (используется по умолчанию);
  • text — добавляет цветные метки разных размеров;
  • markers — добавляет цветные круги разных размеров.

JavaScript interactive map Webix GeoChart with markers

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

webix.ui({
  view:"geochart",
  //...config
    chart:{
      displayMode:"markers"
    }
});

Если данные имеют несколько столбцов, то размер кругов зависит от второго числового столбца — население (population) в моих данных. 

Я также могу динамически изменять режим с помощью setDisplayMode (”markers»). Например, давайте добавим сегментированную кнопку, которая будет переключать GeoChart в разные режимы. Я помещу кнопку на боковую панель: 

var chartForm = {
  view:"form", id:"chartForm", elements:[
    {view:"segmented", id:"modes", value:"Regions",  
      options:["Markers","Regions","Text"],
      click:function(){
        $$("map").setDisplayMode(this.getValue().toLowerCase());
    }}
  ]
};

Webix GeoChart modes

Мне бы хотелось иметь возможность спрятать боковую панель. Поэтому я помещаю форму в  Webix Accordion:

var form = {
  header:"Configure", body:{
    width:300, type:"wide", rows:[
      chartForm
    ]
}};

Легенды и цвета

Давайте раскрасим GeoChart. Во-первых, я изменю цветовую схему легенды и раскрашу карту в цвета радуги. Для этого я установлю свойство chart.colorAxis:

chart:{
  colorAxis: {  
    colors:['violet','indigo','blue','green','yellow','orange','red']  
  }
  //...
}

Атрибут colors также принимает шестнадцатеричные значения. Цветовая схема легенды может быть изменена динамически с помощью настройки config.chart.colorAxis. Давайте добавим другие цветовые схемы и кнопку для переключения между ними: 

{ view:"segmented", id:"colors", value:"Rainbow",
  options:["Rainbow", "Volcano"],
  click:function(){
    var color = this.getValue();
    switch(color){
      case "Rainbow":
        $$("map").config.chart.colorAxis = {colors: ['violet','indigo','blue','green','yellow','orange','red']};
        $$("map").refresh();
      break;
      case "Volcano":
        $$("map").config.chart.colorAxis = {colors: ["#e7711c", "#4374e0"]};
        $$("map").refresh();
      break;
    }
}}

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

Теперь я изменю цвет фона свойством chart.backgroundColor. Цвет областей без данных можно задать с помощью chart.datalessRegionColor. 

Webix GeoChart with different colors - gif

Демо >>

Легенда карты может быть дополнительно настроена и даже скрыта. Для получения более подробной информации ознакомьтесь с API Google GeoChart

Регионы и страны в GeoChart

Я также хочу, чтобы моя интерактивная карта показывала конкретные регионы или страны. Это можно сделать с помощью свойства chart.region. Оно принимает коды стран, такие как «US » или «BY», коды регионов, такие как «142 «(для Азии) и ‘world’. Список поддерживаемых кодов можно найти в разделе иерархия континентов и коды

Помимо установки начальной региональной конфигурации GeoChart, я могу динамически изменять отображаемую область с помощью setRegion (”code»). Давайте добавим радиоуправление на боковую панель. Радио переключит GeoChart с картины мира на другие континенты: 

{view:"radio", id:"regions", value:1, vertical:true,
  options:[ {id:1, value:"World"}, {id:2, value:"Europe"} ],  
  click:function(){
    var region = $$("regions").getValue();
    switch(region){
      case "1":
        $$("map").setRegion("world");
        break;
      case "2":
        $$("map").setRegion("150");
        break;
}}}

Webix with Google GeoChart region Europe

Подсказки

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

tooltip:"<i>Area</i>: #area#"

Кроме того, я могу стилизовать всплывающие подсказки. Я сделаю это, обратившись к классу .google-visualization-tooltip class:

.google-visualization-tooltip {
    background-color: lightblue;
    border: 1px solid #ccc;
    box-shadow: 0 2px 2px 0 rgba(204, 204, 204, 0.6);
}

Webix GeoChart a different tooltip

В посте на Stack Overflow вы найдете более подробные советы по стилизации всплывающих подсказок. 

Данные с несколькими столбцами

В случае данных, где элементы сравниваются по нескольким параметрам, например, по площади и населению, я могу выбрать, какой параметр отображать на карте. Остальные столбцы можно отобразить во всплывающих подсказках. Чтобы получить такой результат, я изменю порядок полей в свойстве columns. Давайте сделаем population (население) столбцом, который будет определять цвета диаграммы. Посмотрите:

var map = {
    view:"geochart",
    id:"map",
    key:"...",
    columns:["country", "population", "area"],
    //...
}

Webix GeoChart with population map

Размер кругов теперь зависит от площади.

Демо>>

Интерактивный GeoChart

Интерактивность в Webix GeoChart включена по умолчанию. Я могу нажать на регионы и круги. Если есть связанные данные, то область будет выделена. Я расширю интерактивность с помощью события onItemClick. Например, давайте выберем строку в таблице DataTable с данными в той же области:

var map = {
  view:"geochart",
  id:”map”,
  key:"...",
  on:{
    onItemClick:function(id){
      $$("grid").select(id);
    }
  }
};

onItemClick срабатывает, когда вы нажимаете на цветную область или круг, т. е. области с данными. 

Я хочу, чтобы была возможность нажимать на любую область, в том числе и без каких-либо данных. Еще одно доступное событие — onRegionClick. Это событие срабатывает только в режиме регионов. Например: 

var map = {
    view:"geochart",
    id:"map",
    key:"...",
    on:{
        onRegionClick:function(obj){
          webix.message(“Region code ”+obj.region);
        }
    }
};

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

Использование GeoChart для редактирования данных

Поскольку GeoChart — это компонент данных, я могу загружать, редактировать и удалять данные из него так же, как и с другими компонентами данных. Давайте добавим форму для редактирования, добавления и удаления элементов GeoChart:

var editForm = {
    view:"form", id:"editForm", elements:[
      { view:"combo", name:"country", options:countries },
      { view:"text", name:"area", label:"Area" },
      { view:"text", name:"population", label:"Population" },
      { view:"button", value:"Add/Update Item" },
      { view:"button", value:"Remove Item" }
    ]
};

Webix GeoChart edit form

combo берет свои опции из DataCollection, которая содержит все названия стран и коды регионов:

var countries = new webix.DataCollection({
  url:"https://docs.webix.com/samples/36_geochart/data/countries.json"
});

/* countries.json
  [
   {
    "value": "Afghanistan",
    "code": "AF",
    "id": "Afghanistan"
   },...
  ]
*/

Когда выбрана страна, я хочу заполнить форму данными, если эта страна уже существует в наборе данных. Если для выбранной области нет данных, пусть форма будет пустой. Чтобы найти элементы данных, я могу вызвать метод find. Однако, поскольку карта в демо-версии синхронизирована с DataCollection, я могу искать элементы методом mapdata:

{ view:"combo", name:"country", options:countries,
  on:{
    onChange:function(newv){
      //is the country in data?
      var item = mapdata.find(function(obj){
        return obj.country.toLowerCase() === newv.toLowerCase();
      });
         
      if(item.length)
        this.getFormView().setValues(item[0]);
      else {
        //if not, get its code
        var itemc = countries.find(function(obj){
          return newv === obj.value;
        },true);
        this.getFormView().setValues({country:newv, code:itemc.code, id:", area:", population:"});
      }
  }
}}

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

Далее, если нет данных, связанных с выбранной страной, код региона будет взят из большого набора данных с помощью countries.find. 

Если массив элементов не пуст, то форма заполняется реальными значениями. В противном случае он получает название страны и код, другие элементы управления заполняются пустыми строками. Обратите внимание на пустую строку, переданную в id. Я использую ее позже как метку, чтобы проверить, находится ли уже страна в DataCollection. 

geochart edit combo list

Добавление и обновление элементов

Теперь я хочу добавить и обновить элементы данных. Здесь есть два варианта:

  1. страна уже находится в наборе данных;
  2. я добавляю новую страну.

Чтобы разобраться с первым случаем, давайте воспользуемся методом updateItem данных DataCollection. У GeoChart есть такой же метод. updateItem принимает два параметра: ID элемента и сам элемент как объект.

{ view:"button", value:"Add/Update Item", click:function(){
  var values = this.getFormView().getValues();
  if(values.id)
    mapdata.updateItem(values.id, { area:values.area, population:values.population});
}}

values.id правдиво, если страна находится в DataCollection.

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

{ view:"button", value:"Add/Update Item", click:function(){
    var values = this.getFormView().getValues();
    if(values.id)
      mapdata.updateItem(values.id, { area:values.area, population:values.population});
    else{
      mapdata.add({ country:values.country, code:values.code, area:values.area, population:values.population});
    }
}}

Было бы неплохо провести валидацию входных данных формы. Для начала я добавлю правила валидации в форму:

var editForm = {
    view:"form", id:"editForm", elements:[
      //elements    
    ],
    rules:{
        area:webix.rules.isNumber,
        population:webix.rules.isNumber,
        country:function(value){ return value != 0; }
    }
};

Теперь я добавлю валидацию в обработчик кнопокAdd/Update:

{ view:"button", value:"Add/Update Item", click:function(){
  if(this.getFormView().validate()){
    var values = this.getFormView().getValues();
    if(values.id)
      mapdata.updateItem(values.id, { area:values.area, population:values.population});
    else{
      mapdata.add({ country:values.country, code:values.code, area:values.area, population:values.population});
    }
  }
}}

Когда я добавляю или обновляю элемент в mapdata, список записей в DataTable также обновляется.

Webix with geochart interactive map cameroon added

Удаление элементов

Теперь давайте включим удаление элементов из GeoChart. Нужно проверить, существует ли элемент, прежде чем удалить его. Я снова буду использовать значение id формы в качестве метки. И GeoChart, и DataCollection имеют метод remove, давайте его использовать.

{ view:"button", value:"Remove Item", click:function(){
    if(this.getFormView().validate()){
      var id = this.getFormView().getValues().id;
      if(id){
        mapdata.remove(id);
        this.getFormView().clear();
      }
    }
}}

remove удаляет страну только после проверки входных данных и если элемент существует в наборе данных. После удаления элемента форма будет очищена.

Еще один момент с интерактивностью

Вот еще один пример того, как повысить интерактивность с помощью события onClick. Довольно удобно редактировать элементы одним кликом по карте. Чтобы обновить страны из DataCollection, я обработаю onItemClick: :

on:{
  onItemClick:function(id){
    $$("editForm").setValues(this.getItem(id));
    $$("grid").select(id);
  }
}

Что ж, это было легко. Затем я хочу добавить новые страны, кликнув на регионы без данных. Эта задача будет сложнее, потому что onRegionClick срабатывает для регионов с данными и без них. 

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

onRegionClick:function(obj){
  var code = obj.region;
  var item = mapdata.find(function(obj){
    return obj.code === code;
  });
     
  if(!item.length) {
    $$("grid").clearSelection();
    webix.confirm("Add a new country?", function(){
      //...add the country
    });
  }
}

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

webix.confirm("Add a new country?", function(result){
  if (result) {
    var newv = countries.find(function(obj){
      return obj.code === code;
    },true);
    $$("editForm").setValues({country:newv.value});
  }
});

Webix GeoChart Interactive Map

А вот и демо с полным исходным кодом.

Прежде чем вы умчитесь наслаждаться GeoChart…

GeoChart хорош для представления различных статистических данных, связанных с регионами, странами или государствами. Вы можете адаптировать GeoChart к вашим потребностям и использовать его в приложениях для бизнеса, образования, отчетов или просто для удовольствия. Если у вас есть какие-либо идеи и советы по GeoChart, буду рада их услышать:)

Получите демо-версию и развлекайтесь. Если вы хотите копнуть глубже и получить более подробную информацию о GeoChart, ознакомьтесь с документацией Webix и документацией Google