Интерактивная SVG-карта на Raphael
Задача
Сделать карту, поделенную на участки произвольной формы. Отдельные участки должны реагировать на наведение мыши и на клик по ним (например, плавно меняя цвет).
Решение
Задачу можно решать с помощью canvas или SVG, но в любом случае, при встрече со старыми (но, к сожалению все еще актуальными) IE, мы натолкнемся на глухую стену непонимания. Для обеспечения кроссбраузерности, воспользуемся замечательной библиотекой Raphael.
Проверено в:
- IE 6-9
- Firefox 14
- Opera 12
- Safari
- Chrome
Что качать?
- библиотеку jquery качаем или подключаем из хранилища.
- raphael.js — собственно плагин
Быстрый старт
Подключаем 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 огромны. Мы затронули только верхушку айсберга — применили ее к конкретной задаче построения интерактивной карты. Подробнее изучить и по достоинству оценить библиотеку можно на ее официальном сайте.
Материал
- Raphaël—JavaScript Library :: официальный сайт