Интерактивная SVG-карта на Raphael
Дата публикации: 16.08.2012
Задача

Сделать карту, поделенную на участки произвольной формы. Отдельные участки должны реагировать на наведение мыши и на клик по ним (например, плавно меняя цвет).
Решение
Задачу можно решать с помощью canvas или SVG, но в любом случае, при встрече со старыми (но, к сожалению все еще актуальными) IE, мы натолкнемся на глухую стену непонимания. Для обеспечения кроссбраузерности, воспользуемся замечательной библиотекой Raphael. Возможно, полезное для вас можно найти здесь https://global-paper.ru/products/2.
Проверено в:
- IE 6-9
- Firefox 14
- Opera 12
- Safari
- Chrome
Что качать?
- библиотеку jquery здесь https://jquery.com/download/ или подключаем из хранилища.
- http://raphaeljs.com/ Raphaël—JavaScript Library :: официальный сайт плагина
Быстрый старт
Подключаем jQuery, и сам плагин:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script> <script src="js/raphael.js"></script>
Создаем в HTML конструкцию, соответствующую карте: контейнер с id (к нему будет обращение из скрипта) и блоки, соответствующие участкам.
<div class="map" id="mapPaper"> <div class="mapArea" data-path="M306,11 415,42 389,86 284,28z"></div> <div class="mapArea" data-path="M284,28 378,80 359,114 349,119 261,46z"></div> <div class="mapArea" data-path="M261,46 349,119 315,148 238,68z"></div> </div>
Участки описываются с помощью SVG путей (path). Если ты не знаком с такими конструкциями почитай статьи Сущность SVG. J. David Eisenberg :: Paths. Moveto, lineto, и closepath и Сущность SVG. J. David Eisenberg :: Сокращение путей.
Составляя правильный path можно получить участки, ограниченные кривой любой сложности.
Координаты вынесены в HTML для удобства их дальнейшего (при необходимости) редактирования — нам уже не придется менять непосредственно скрипт.
В CSS задаем размеры и фоновый рисунок:
#mapPaper {
width: 455px;
height: 358px;
background: url(images/map.jpg) no-repeat;
}
Теперь собственно сам скрипт:
jQuery(document).ready(function(){
var R = Raphael("mapPaper", 455, 358);
var attr = {
stroke: "#74675C",
"stroke-width": 1,
fill: "#FC0"
},
i = 1,
area = {};
var oAreas = $(".mapArea");
$.each(oAreas, function(){
area[i] = R.path($(this).attr("data-path")).attr(attr);
i++;
});
for (var j=1; j<i; j++) {
(function (o, j) {
o[0].style.cursor = "pointer";
o[0].onmouseover = function () {
var color = "#FCE588";
o.animate({fill:color}, 250);
};
o[0].onmouseout = function () {
var color = "#FC0";
o.animate({fill: color}, 250);
};
o[0].onclick = function () {
var color = "#F00";
o.animate({fill: color}, 250);
};
})(area[j], j);
}
});
Вот, собственно, и все.
Смотрим скрипт подробнее
Разберем только ключевые участки. Инициализируем плагин, указывая полотно (по id) и его размеры. В переменной attr задаем параметры кисти (цвет, толщину, цвет заливки)
var R = Raphael("mapPaper", 455, 358);
var attr = {
stroke: "#74675C",
"stroke-width": 1,
fill: "#FC0"
}
Далее идет своего рода микропарсер. Читаем искуcственные атрибуты data-path, содержащие пути, и создаем на их основе массив объектов area (в этот момент участки отрисуются на холсте).
i = 1,
area = {};
var oAreas = $(".mapArea");
$.each(oAreas, function(){
area[i] = R.path($(this).attr("data-path")).attr(attr);
i++;
});
После всего проделанного, к объектам area можно подцепить события, например, так:
for (var j=1; j<i; j++) {
(function (o, j) {
o[0].onmouseover = function () {
var color = "#FCE588";
o.animate({fill:color}, 250);
};
})(area[j], j);
}
Выводы
Графические и анимационные возможности библиотеки Raphael огромны. Мы затронули только верхушку айсберга — применили ее к конкретной задаче построения интерактивной карты. Подробнее изучить и по достоинству оценить библиотеку можно на ее официальном сайте.
