Построение интерактивной карты с Raphaël

Raphaël — это мощная библиотека, которая должна упростить работу с векторной графикой в Интернете. Сегодня я научу вас, как создать интерактивную карту с нуля.

Для начала, пожалуйста, создайте следующую структуру папок и файлов:

Структура папок и файлов

Raphaël (raphael.js)

Raphaël — небольшая библиотека на JavaScript, которая должна упростить вашу работу с векторной графикой. Raphaël использует SVG и VML в качестве основы для создания графики. Это означает, что каждый графический объект который вы создаёте, также является объектом DOM, так что к нему можно добавить обработчик событий JavaScript или модифицировать его позднее.

paths.js

Это файл, в котором мы будем хранить контуры и названия каждой страны.

index.html

Как обычно, первым шагом будет создание разметки HTML.


<!DOCTYPE html>   
<html>   
 <head>   
 <meta charset="utf-8">   
 <title>Построение интерактивной карты с Raphaël</title>   
 <link href="css/default.css" rel="stylesheet">   
 <script src="js/jquery.js"></script>   
 <script src="js/raphael.js"></script>   
 <script src="js/paths.js"></script>   
 <script src="js/init.js"></script>   
 </head>     
 <body>   
 <div id="map"></div>   
 </body>   
</html>

Мы также вставляем стили (default.css) и перед закрытием тега включаем библиотеку jQuery, библиотеку Raphaël, paths.js и init.js.

Создание контуров из файла SVG

SVG (Scalable Vector Graphics, масштабируемая векторная графика) это семейство спецификаций основанной на формате XML для описания двумерной векторной графики.

Это определение сообщает, что SVG является файлом XML, так что вы сможете открыть его в текстовом редакторе. Я нашел в Интернете свободный SVG-файл с картой Европы, который и собираюсь использовать в этом уроке. Очевидно, что вы можете использовать собственную векторную карту и экспортировать её в SVG-файл с помощью программы Adobe Illustrator или Inkspace.

Открываем paths.js и создаём новый объект с именем paths.


var paths = {}

Затем откройте SVG-файл с картой и вы увидите много кода XML. К счастью, вам нужно только одно значение d. Посмотрите на изображение ниже.

Значение d

Давайте создадим первый контур страны. В SVG-файле, использованном в этом уроке, первой идёт Исландия, поэтому скопируйте значение d и создайте новый параметр iceland в объекте paths.


var paths = {
 iceland: {
  name: 'Iceland',
  path: // Значение d
 }
}

Таким же образом добавляются и другие контуры.


var paths = {
 iceland: {
  name: 'Iceland',
  path: // Значение d
 },
 spain: {
  name: 'Spain',
  path: // Значение d
 },
 portugal: {
  name: 'Portugal',
  path: // Значение d
 }
 // и т.д.
}

Создание карты (init.js)

В этой части урока я собираюсь написать скрипт, который будет показывать карту на экране.


$(function(){
 var r = Raphael('map', 1200, 820),
  // создаём холст, на котором рисуются наши контуры
  attributes = {
   fill: '#fff',
   stroke: '#3899E6',
   'stroke-width': 1,
   'stroke-linejoin': 'round'
  },
  // создаём объект attributes с параметрами
  arr = new Array();
   for (var country in paths) {
    var obj = r.path(paths[country].path);
    obj.attr(attributes);
   }
  // в цикле обходим все контуры (контуры, которые включены в объект paths),
  // показываем их и устанавливаем для них параметры
});

В первую очередь создадим событие hover.


obj.hover(function(){
 this.animate({
  fill: '#1669AD'
 }, 300);
}, function(){
 this.animate({
  fill: attributes.fill
 }, 300);
});

Далее добавим событие click.


obj.click(function(){
 document.location.hash = arr[this.id];
 // меняем адрес документа (после #)
 var point = this.getBBox(0);
 // возвращает размер элемента
 $('#map').next('.point').remove();
 $('#map').after($('<div></div>').addClass('point'));
 // удаляем существующий div с классом point и создаём ещё один
 $('.point')
 .html(paths[arr[this.id]].name)
 .prepend($('<a></a>').attr('href', '#').addClass('close').text('Close'))
 .prepend($('<img />').attr('src', 'flags/'+arr[this.id]+'.png'))
 .css({
 left: point.x+(point.width/2)-80,
 top: point.y+(point.height/2)-20
 })
 .fadeIn();
 // добавляем контент (название страны, рисунок и кнопку закрытия),
 // задаём позицию и показваем элемент
});

И обработчик для кнопки «закрыть».


$('.point').find('.close').live('click', function(){
 var t = $(this),
  parent = t.parent('.point');
 parent.fadeOut(function(){
  parent.remove();
 });
 return false;
});

Окончательно init.js выглядит так:


$(function(){
 var r = Raphael('map', 1200, 820),
 attributes = {
  fill: '#fff',
  stroke: '#3899E6',
  'stroke-width': 1,
  'stroke-linejoin': 'round'
 },
 arr = new Array();
 for (var country in paths) {
  var obj = r.path(paths[country].path);
  obj.attr(attributes);
  arr[obj.id] = country;
  obj
  .hover(function(){
   this.animate({
    fill: '#1669AD'
   }, 300);
  }, function(){
   this.animate({
    fill: attributes.fill
   }, 300);
  })
  .click(function(){
   document.location.hash = arr[this.id];
   var point = this.getBBox(0);
   $('#map').next('.point').remove();
   $('#map').after($('<div></div>').addClass('point'));
   $('.point')
   .html(paths[arr[this.id]].name)
   .prepend($('<a></a>').attr('href', '#').addClass('close').text('Close'))
   .prepend($('<img />').attr('src', 'flags/'+arr[this.id]+'.png'))
   .css({
    left: point.x+(point.width/2)-80,
    top: point.y+(point.height/2)-20
   })
   .fadeIn();
  });
  $('.point').find('.close').live('click', function(){
   var t = $(this),
   parent = t.parent('.point');
   parent.fadeOut(function(){
    parent.remove();
   });
   return false;
  });
 }
});

default.css

Последний шаг состоит в добавлении некоторого стиля с помощью CSS.


#map {
 float:left;
 clear:both;
 width:1200px;
 height:820px;
}
   
.point {
 position:absolute;
 display:none;
 padding:10px 15px;
 background:#7BB9F0;
 font-size:14px;
 font-weight:bold;
 /* скруглённые уголки */
 -moz-border-radius:8px;
 -webkit-border-radius:8px;
 border-radius:8px;
}
   
.point .close {
 display:block;
 position:absolute;
 top:-10px;
 right:-10px;
 width:24px;
 height:24px;
 text-indent:-9999px;
 outline:none;
 background:url(../img/close.png) no-repeat;
}
   
.point img {
 vertical-align:middle;
 margin-right:10px;
}

Данная публикация является переводом статьи Marcin Dziewulski «Building an interactive map with Raphael«. Автор перевода Влад Мержевич.

Ссылки

Источник: https://www.kobzarev.com/programming/raphael-interactive-map/

Михаил Кобзарёв

Суровый русский тимлид. Жил в Магадане, в офисе московских веб студий и в Тульской деревне. Виртуозно знает WordPress, PHP, ООП, Vue.js и вот это вот все. Делает крутые высоконагруженные сайты, поэтому уже почти захватил весь рынок WordPress разработки в России. Не дает никому делать сайты без спроса. Ведет блог о разработке, дайджест в телеграмме и в ВК. Любит сиськи, баню и радиоэлектронику. 100% патриот (но это не точно). Тролль 542 уровня. Ездит в отпуск раз в 5 лет.

Добавить комментарий

%d такие блоггеры, как: