Новый Webix 5.0 включает в себя виджет JavaScript GeoChart, созданный с помощью Google Maps API. GeoChart — это изящный сервис для создания картографических диаграмм c отображением данных стран и регионов. Я покажу вам, как использовать основные функции виджета для создания интерактивной карты мира. Если вы еще не знакомы с виджетом, я надеюсь, что GeoChart станет вашим верным другом. Если вы уже любите GeoChart так же сильно, как я, вы, вероятно, получите лучшее представление о том, как можно с ним взаимодействовать.
Базовый GeoChart для отображения данных
Во-первых, давайте покажем данные в режиме readonly (только для чтения). Макет приложения будет иметь три панели:
- карта
- боковая панель с элементами управления
- нижняя панель с записями данных
Прежде чем инициализировать GeoChart, не забудьте получить свой личный ключ.
Несколько строк кода добавят GeoChart в приложение. Вот простая карта с небольшими данными:
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 и в виде списка записей под картой.
{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:
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:
view:"datatable", id:"grid", autoheight:true,
scroll:false, autoConfig:true
}
Вот макет:
cols:[
form,
{ view:"scrollview", body:{
type:"clean", rows:[
map,
grid
]
}}
]
});
form на данный момент — это просто шаблон, который резервирует место для элементов управления на боковой панели. Карта и DataTable заключены в представление scrollview, чтобы адаптировать демонстрацию под изменения размера. Для этой же цели я отключила прокрутку сетки по умолчанию.
Чтобы синхронизировать GeoChart и DataTable с DataCollection, вызываем sync:
$$("grid").data.sync(mapdata);
Режимы GeoChart
GeoChart имеет множество опций, которые могут изменить внешний вид карты. Например, существует три способа пометить области со связанными данными:
- regions — цветовые области карты (используется по умолчанию);
- text — добавляет цветные метки разных размеров;
- markers — добавляет цветные круги разных размеров.
Я могу изменить режим, установив свойство chart.displayMode. Например, чтобы показать круги на графике, я установлю свойство маркерам:
view:"geochart",
//...config
chart:{
displayMode:"markers"
}
});
Если данные имеют несколько столбцов, то размер кругов зависит от второго числового столбца — население (population) в моих данных.
Я также могу динамически изменять режим с помощью setDisplayMode (”markers»). Например, давайте добавим сегментированную кнопку, которая будет переключать GeoChart в разные режимы. Я помещу кнопку на боковую панель:
view:"form", id:"chartForm", elements:[
{view:"segmented", id:"modes", value:"Regions",
options:["Markers","Regions","Text"],
click:function(){
$$("map").setDisplayMode(this.getValue().toLowerCase());
}}
]
};
Мне бы хотелось иметь возможность спрятать боковую панель. Поэтому я помещаю форму в Webix Accordion:
header:"Configure", body:{
width:300, type:"wide", rows:[
chartForm
]
}};
Легенды и цвета
Давайте раскрасим GeoChart. Во-первых, я изменю цветовую схему легенды и раскрашу карту в цвета радуги. Для этого я установлю свойство chart.colorAxis:
colorAxis: {
colors:['violet','indigo','blue','green','yellow','orange','red']
}
//...
}
Атрибут colors также принимает шестнадцатеричные значения. Цветовая схема легенды может быть изменена динамически с помощью настройки config.chart.colorAxis. Давайте добавим другие цветовые схемы и кнопку для переключения между ними:
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.
Легенда карты может быть дополнительно настроена и даже скрыта. Для получения более подробной информации ознакомьтесь с API Google GeoChart.
Регионы и страны в GeoChart
Я также хочу, чтобы моя интерактивная карта показывала конкретные регионы или страны. Это можно сделать с помощью свойства chart.region. Оно принимает коды стран, такие как «US » или «BY», коды регионов, такие как «142 «(для Азии) и ‘world’. Список поддерживаемых кодов можно найти в разделе иерархия континентов и коды.
Помимо установки начальной региональной конфигурации GeoChart, я могу динамически изменять отображаемую область с помощью setRegion (”code»). Давайте добавим радиоуправление на боковую панель. Радио переключит GeoChart с картины мира на другие континенты:
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 GeoChart имеет HTML подсказки, которые показывают подробную информацию о каждой области в наборе данных. Всплывающие подсказки появляются, когда пользователь наводит указатель мыши на область или круг. По умолчанию всплывающие подсказки показывают список всех столбцов данных. Я могу изменить содержимое всплывающих подсказок по умолчанию, перечислив столбцы, которые я хочу показать, например, с помощью этого кода всплывающая подсказка будет показывать только область area:
Кроме того, я могу стилизовать всплывающие подсказки. Я сделаю это, обратившись к классу .google-visualization-tooltip class:
background-color: lightblue;
border: 1px solid #ccc;
box-shadow: 0 2px 2px 0 rgba(204, 204, 204, 0.6);
}
В посте на Stack Overflow вы найдете более подробные советы по стилизации всплывающих подсказок.
Данные с несколькими столбцами
В случае данных, где элементы сравниваются по нескольким параметрам, например, по площади и населению, я могу выбрать, какой параметр отображать на карте. Остальные столбцы можно отобразить во всплывающих подсказках. Чтобы получить такой результат, я изменю порядок полей в свойстве columns. Давайте сделаем population (население) столбцом, который будет определять цвета диаграммы. Посмотрите:
view:"geochart",
id:"map",
key:"...",
columns:["country", "population", "area"],
//...
}
Размер кругов теперь зависит от площади.
Интерактивный GeoChart
Интерактивность в Webix GeoChart включена по умолчанию. Я могу нажать на регионы и круги. Если есть связанные данные, то область будет выделена. Я расширю интерактивность с помощью события onItemClick. Например, давайте выберем строку в таблице DataTable с данными в той же области:
view:"geochart",
id:”map”,
key:"...",
on:{
onItemClick:function(id){
$$("grid").select(id);
}
}
};
onItemClick срабатывает, когда вы нажимаете на цветную область или круг, т. е. области с данными.
Я хочу, чтобы была возможность нажимать на любую область, в том числе и без каких-либо данных. Еще одно доступное событие — onRegionClick. Это событие срабатывает только в режиме регионов. Например:
view:"geochart",
id:"map",
key:"...",
on:{
onRegionClick:function(obj){
webix.message(“Region code ”+obj.region);
}
}
};
Обработчик событий получает объект с кодом региона. В следующем шаге я покажу вам еще один пример обработки этих событий.
Использование GeoChart для редактирования данных
Поскольку GeoChart — это компонент данных, я могу загружать, редактировать и удалять данные из него так же, как и с другими компонентами данных. Давайте добавим форму для редактирования, добавления и удаления элементов GeoChart:
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" }
]
};
combo берет свои опции из DataCollection, которая содержит все названия стран и коды регионов:
url:"https://docs.webix.com/samples/36_geochart/data/countries.json"
});
/* countries.json
[
{
"value": "Afghanistan",
"code": "AF",
"id": "Afghanistan"
},...
]
*/
Когда выбрана страна, я хочу заполнить форму данными, если эта страна уже существует в наборе данных. Если для выбранной области нет данных, пусть форма будет пустой. Чтобы найти элементы данных, я могу вызвать метод find. Однако, поскольку карта в демо-версии синхронизирована с DataCollection, я могу искать элементы методом mapdata:
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.
Добавление и обновление элементов
Теперь я хочу добавить и обновить элементы данных. Здесь есть два варианта:
- страна уже находится в наборе данных;
- я добавляю новую страну.
Чтобы разобраться с первым случаем, давайте воспользуемся методом updateItem данных DataCollection. У GeoChart есть такой же метод. updateItem принимает два параметра: ID элемента и сам элемент как объект.
var values = this.getFormView().getValues();
if(values.id)
mapdata.updateItem(values.id, { area:values.area, population:values.population});
}}
values.id правдиво, если страна находится в DataCollection.
Теперь давайте рассмотрим второй случай: добавление новой страны в набор данных. Я буду использовать метод add, который получает один обязательный параметр — объект country.
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});
}
}}
Было бы неплохо провести валидацию входных данных формы. Для начала я добавлю правила валидации в форму:
view:"form", id:"editForm", elements:[
//elements
],
rules:{
area:webix.rules.isNumber,
population:webix.rules.isNumber,
country:function(value){ return value != 0; }
}
};
Теперь я добавлю валидацию в обработчик кнопокAdd/Update:
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 также обновляется.
Удаление элементов
Теперь давайте включим удаление элементов из GeoChart. Нужно проверить, существует ли элемент, прежде чем удалить его. Я снова буду использовать значение id формы в качестве метки. И GeoChart, и DataCollection имеют метод remove, давайте его использовать.
if(this.getFormView().validate()){
var id = this.getFormView().getValues().id;
if(id){
mapdata.remove(id);
this.getFormView().clear();
}
}
}}
remove удаляет страну только после проверки входных данных и если элемент существует в наборе данных. После удаления элемента форма будет очищена.
Еще один момент с интерактивностью
Вот еще один пример того, как повысить интерактивность с помощью события onClick. Довольно удобно редактировать элементы одним кликом по карте. Чтобы обновить страны из DataCollection, я обработаю onItemClick: :
onItemClick:function(id){
$$("editForm").setValues(this.getItem(id));
$$("grid").select(id);
}
}
Что ж, это было легко. Затем я хочу добавить новые страны, кликнув на регионы без данных. Эта задача будет сложнее, потому что onRegionClick срабатывает для регионов с данными и без них.
Я возьму код региона, полученный из события, и сравню его с кодами в списке стран, отмеченных на карте. Затем, если результат поиска пуст, окно подтверждения Webix спросит пользователей, хотят ли они добавить новую запись. Если да, то они могут перейти к добавлению нового элемента.
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 будет изменено.
if (result) {
var newv = countries.find(function(obj){
return obj.code === code;
},true);
$$("editForm").setValues({country:newv.value});
}
});
А вот и демо с полным исходным кодом.
Прежде чем вы умчитесь наслаждаться GeoChart…
GeoChart хорош для представления различных статистических данных, связанных с регионами, странами или государствами. Вы можете адаптировать GeoChart к вашим потребностям и использовать его в приложениях для бизнеса, образования, отчетов или просто для удовольствия. Если у вас есть какие-либо идеи и советы по GeoChart, буду рада их услышать:)
Получите демо-версию и развлекайтесь. Если вы хотите копнуть глубже и получить более подробную информацию о GeoChart, ознакомьтесь с документацией Webix и документацией Google.