Когда мне нужно создать карты, то первым делом, я обращаюсь к Google Charts или любой другой специализированн
Недавно, мне нужно было проектировать страницу отчета, которая могла бы показывать карту Италии, на которой каждый регион имел бы свой цвет, в зависимости от некоторых значений выборки из базы данных. Благодаря SVG, эта задача стала очень простой.
Создаем SVG карту в Illustrator
Первым делом я нарисовал карту Италии в Adobe Illustrator:
Каждый регион рисовался как отдельный объект, который помещался на свой отдельный слой, с названием совпадающим с кодом, используемом в базе данных, чтобы определить соотносимые данные (например, «tos» для Тосканы).
Наконец, карта должна быть сохранена в формате SVG. Вам следует обратить внимание на то, чтобы установить опцию «CSS property» в графе «Элементы стиля» в Иллюстраторе, как показано ниже:
Открыв только что созданный файл, вы увидите, что он содержит набор тегов g, идентификаторы которого совпадают с названиями уровней в Illustrator.
Построение нашего HTML файла
Каждый элемент, содержащийся в тегах g имеет класс st0, так чтобы обводки и заливки CSSс войства <strong>stroke</strong> и fill:
Если вы попытаетесь изменить эти значения, карта изменится тоже:
Теперь мы можем использовать этот код, чтобы создать наш HTML файл со встроенным SVG, как показано ниже (код был сокращен для удобства):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Map Sample</title>
</head>
<body>
<div class="map">
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 -21.6 761 919" style="enable-background:new 0 -21.6 761 919;" xml:space="preserve">
<g id="sar">
<polygon class="st0" points="193,463 ... "/>
</g>
<!-- etc ... -->
</svg>
</div>
</body>
</html>
|
Можно заметить, что атрибут style из тега svg был перенесен в секцию head, и все элементы g изначально залиты светло-серым цветом.
Класс st0 уже не используется (его можно удалить из вашего кода), и он был заменен селектором .map g. В любом случае, это не было обязательным действием – вы можете использовать любые CSS селекторы – на ваше усмотрение.
Вторым шагом надо привязать нашу карту к данным, получаемым из внешнего источника. В данном примере мы будет раскрашивать регионы в цвета, зависящие от населенности этих регионов.
Добавляем JSON-данные и JavaScript
Данные мы получаем в формате JSON, и вставляем их в HTML файл напрямую (в реальных условиях, мы, конечно же, будет получать данные по Ajax, или подобным способом).
Теперь наша страница будет содержать JSON внутри нашего файла с JavaScript, который будет выглядеть примерно так:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var regions=[
{
"region_name": "Lombardia",
"region_code": "lom",
"population": 9794525
},
{
"region_name": "Campania",
"region_code": "cam",
"population": 5769750
},
// etc ...
];
|
После этого мы выбираем цвет (в данном случае – #0b68aa), и принимаем его за цвет региона с самым большим населением. Остальные регионы будут раскрашены в тона основного цвета в пропорциях процента населенности (по отношению к максимальному населению).
Далее мы добавим немного JavaScript.
Первым делом надо определить регион с самым большим населением. Это можно сделать несколькими строчками кода.
Как только мы составим массив со значениями размера населения, из него можно получить максимальное значение с помощью метода Math.max:
1
2
3
4
5
|
var temp_array= regions.map( function( item ) {
return item.population;
});
var highest_value = Math.max.apply( Math, temp_array );
|
Далее можно пройтись по всем элементам regions, и применить уровень прозрачности, в зависимости от вычисленного параметра население / максимальное значение (с небольшой помощью jQuery):
1
2
3
4
5
6
7
|
$(function() {
for(i=0; i < regions.length; i++) {
$('#'+ regions[i].region_code).css({'fill': 'rgba(11, 104, 170,'
+ regions[i].population/highest_value
+ ')'});
}
});
|
А вот и результат:
Добавляем интерактивности с помощью CSS и jQuery
Карту можно улучшить, добавив немного интерактивности. Нам бы хотелось показать размер населения при наведении курсора на регион.
Сначала добавим правила CSS для селектора g:hover и класса info_panel, чтобы стилизовать информационный всплывающий блок:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
.map g:hover {
fill: #fc0 !important;
cursor: help;
}
.info_panel {
background-color: rgba(255,255,255, .7);
padding: .3em;
font-size: .8em;
font-family: Helvetica, Arial, sans-serif;
position: absolute;
}
.info_panel::first-line {
font-weight: bold;
}
|
Модификатор !important в селекторе .map g:hover нужен для того, чтобы переопределить свойство fill, иначе будет использовано правило встроенного в элемент CSS.
Также нам нужно модифицировать цикл for, определенный ранее, чтобы добавить data-атрибут, в котором будет хранится значение, отображаемое при наведении:
1
2
3
4
5
6
|
for (i = 0; i < regions.length; i++) {
$('#'+ regions[i].region_code)
.css({'fill': 'rgba(11, 104, 170,'
+ regions[i].population/highest_value
+')'}).data('region', regions[i]);
}
|
И, наконец, разнообразим наш скрипт добавлением некоторых эффектов при наведении:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
$('.map g').mouseover(function (e) {
var region_data=$(this).data('region');
$('
'
+ region_data.region_name
+ '
'
+ 'Population: '
+ region_data.population.toLocaleString("en-UK")
+ ' ').appendTo('body');
}).mouseleave(function () {
$('.info_panel').remove();
}).mousemove(function(e) {
var mouseX = e.pageX, // X coordinates of mouse
mouseY = e.pageY; // Y coordinates of mouse
$('.info_panel').css({
top: mouseY-50,
left: mouseX - ($('.info_panel').width() / 2)
});
});
|
Как это работает:
- с помощью mouseover мы добавили элемент div, содержащий отображаемую информацию (имя региона и населенность). Div создается при каждом наведении на элемент g, и добавляется в элемент body документа;
- mouseleave удаляет этот div, когда курсор выходит за пределы региона;
- последний метод, mousemove, получает координаты мыши, и применяет их к сгенерированным div’ам.
-
See the Pen Dynamic Geo Map with SVG and jQuery by SitePoint (@SitePoint) on CodePen.
Перевод статьи