ДОСТУПНА НОВАЯ ВЕРСИЯ! Webix 11 Подробнее Обновления в Core, SpreadSheet, File Manager и Report Manager и многое другое

Интерактивная карта 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.