JavaScript скрипты
Cоздание ролловеров на картах: imagemap + canvas
Нечто подобное я уже описывал в статье CSS Sprites и их использование. Там описывалось как можно создавать ролловер-эффекты при помощи CSS. В данном примере будем рассматривать использование imagemap + canvas
Ролловер (rollover)
Ролловер (rollover) - это интерактивный графический элемент, к примеру изображение, которое начинает изменяться при наведении на него курсора мыши или при клике. Как правило ролловеры представляют из себя несколько изображений, сменяемых яваскриптом (или через CSS) при определенных событиях. В нашем случае необходимо, чтобы при наведении курсора мыши на участок имэджмапы менялся внешний вид только этого участка, не затрагивая карту в целом. Слабо?О том, что такое карты изображений, и как их создавать, читаем здесь.
Также предварительно знакомимся с canvas и методом "рисования" многоугольников.
JavaScript и HTML
Итак, мы умеем рисовать карты изображений (HTML) и создавать совершенно произвольные многоугольники (Canvas + JavaScript). Объединяем эти знания и получим карту, на которой можно показывать ролловеры по её отдельным областям. Одолеем простую задачу: затемним участок карты изображения при наведении курсора мыши.
Для этого в верстке будем использовать модель пирога со следующими слоями:
1) Верхний: прозрачный ГИФ, к которому привязана имеджмапа
2) Средний: блок Canvas
3) Нижний: Само изображение с картой.
Естественно, ширина и высота всех слоев равна одна другой.
Смотрим HTML & CSS:
canvas {position:absolute; top:10px; left:10px; z-index:20;}
img {position:absolute; top:10px; left:10px; border:0;}
.first {z-index:30;}
.last {z-index:10;}
<!-- Выводим тот самый слоеный пирог -->
<img class="first" src="/images/spacer.gif" width="220" height="140" alt="" usemap="#map1">
<canvas id="canvasId" width="220" height="140"></canvas>
<img class="last" src="/images/articles/pribaltika.gif" width="220" height="140" alt="">
<!-- Разметка имэджмапы -->
<map name="map1" id="imageMapId">
<area shape="poly" alt="Эстония" coords="144,44, 136,47, 136,51, 145,54, 143,68, 141,73, 142,82, 144,90, 149,93, 149,100, 157,100, 161,102, 166,100, 174,91, 183,88, 183,86, 187,83, 208,83, 208,85, 214,85, 217,80, 217,78, 210,76, 205,69, 206,62, 198,43, 198,40, 193,39, 192,30, 186,28, 186,25, 181,24, 181,21, 177,20, 171,14, 168,15, 165,13, 163,17, 158,17, 154,21, 154,24, 156,24, 156,25, 153,25, 144,29, 145,34, 143,39, 151,41, 149,44" href="#Эстония">
<area shape="poly" alt="Латвия" coords="52,12, 43,16, 52,29, 58,30, 58,36, 56,51, 58,60, 63,61, 67,70, 67,72, 66,75, 71,74, 74,88, 84,106, 84,115, 82,120, 86,123, 90,123, 92,127, 94,133, 100,133, 108,135, 115,137, 128,126, 128,124, 131,123, 131,116, 139,115, 146,115, 146,108, 149,104, 149,93, 144,90, 142,82, 141,73, 143,68, 145,54, 136,51, 136,47, 130,48, 114,57, 108,57, 99,50, 100,39, 107,34, 112,21, 115,21, 115,16, 110,13, 104,6, 89,3, 81,7, 71,3, 63,7, 54,9" href="#Латвия">
<area shape="poly" alt="Литва" coords="13,80, 13,70, 9,65, 13,63, 13,60, 19,59, 25,59, 31,54, 30,51, 25,43, 26,30, 29,21, 39,16, 43,16, 52,29, 58,30, 58,35, 56,50, 58,60, 63,61, 67,70, 67,72, 66,75, 71,74, 74,87, 84,106, 84,115, 82,120, 77,121, 73,116, 68,117, 57,120, 48,120, 38,115, 34,116, 31,118, 29,118, 29,110, 30,107, 26,105, 10,105, 7,99, 8,93, 3,92, 3,86" href="#Литва">
</map>
Работа для JavaScript
Нам необходимо знать, над какой областью проводит в данным момент пользователь курсором мыши. Для этого "прикрутим" с помощью функции initImageMap обработчики событий mouseover & mouseout для элементов area. Одновременно кешируем в массив координаты. Для определения поддержки клиентским браузером canvas-а воспользуемся функцией canvasBrowser:
function canvasBrowser() {
// Определяем тип браузера
var ua = navigator.userAgent.toLowerCase();
var isIE = (ua.indexOf("msie") != -1 && ua.indexOf("opera") == -1 && ua.indexOf("webtv") == -1);
var isOpera = ua.indexOf("opera") != -1;
var isFF = ua.indexOf("firefox") != -1;
var result = false;
// Разрешим все версии IE
if (isIE) result = true;
// Лису разрешим только с полторашки
else if (isFF) {
var ffVersion = parseFloat(ua.substring(ua.indexOf("firefox") + 8, ua.length));
if (ffVersion >= 1.5) result = true;
// Оперу, начиная с версии 9.0
} else if (isOpera) {
var operaVersion = parseFloat(ua.substring(ua.indexOf("opera") + 6, ua.length));
if (operaVersion >= 9.0) result = true;
}
return result;
}
// Кеш координат
var coordsCashe = [];
// Прикручиваем события
function initImageMap() {
if (!canvasBrowser()) return;
var map = document.getElementById("imageMapId");
var area, i;
for (i = 0; i < map.childNodes.length; i++) {
area = map.childNodes[i];
// Проверяем тип узла
if (area.nodeType != 1) continue;
// Проверяем, что узел является элементом area
if (area.nodeName.toLowerCase() != "area") continue;
// Добавляем ID c ключом массива координат
area.id = "id" + i;
// Добавляем к элементу обработчики событий
area.onmouseover = mouseOverHandler;
area.onmouseout = mouseOutHandler;
// Кешируем координаты
coordsCashe[i] = parseCoords(area.coords);
}
}
// Обработчик события mouseover
function mouseOverHandler() {
// Вырезаем индекс для массива координат из ID
var i = this.id.substring(2, this.id.length);
// Рисуем многоугольник на полученной области
drawPoly(
"canvasId",
coordsCashe[i]
);
}
// Обработчик события mouseout
function mouseOutHandler() {
// Стираем нарисованное в canvas
clearCanvas("canvasId");
}
// Парсим строку с координатами, перечисленными через запятую, в двумерный массив
function parseCoords(str) {
var coords = [];
var buferArray = str.split(",");
var j = 0;
for (var i = 0; i < buferArray.length; i++) {
if (i % 2 == 0) {
coords[j] = [];
coords[j][0] = buferArray[i];
} else {
coords[j][1] = buferArray[i];
j++;
}
}
return coords;
}
Теперь функции, занимающиеся отрисовкой многоугольников и их стиранием в canvas:
// Функция, принимающая id тега <canvas> и массив координат
function drawPoly(id, arr) {
var canvas = document.getElementById(id).getContext('2d');
// Начинаем отрисовку
canvas.beginPath();
for (var i = 0; i < arr.length; i++) {
// Ставим точку на исходную позицию
if (i == 0) canvas.moveTo(arr[i][0], arr[i][1]);
// Рисуем линии от точки к точке
else canvas.lineTo(arr[i][0], arr[i][1]);
}
// Задаем цвет заливки в формате RGBA
canvas.fillStyle = "rgba(128,128,128,0.7)";
// Зальем полученный многоугольник цветом
canvas.fill();
}
// Очищаем область Canvas
function clearCanvas(id) {
var canvas = document.getElementById(id)
var width = parseInt(canvas.width);
var height = parseInt(canvas.height);
canvas = canvas.getContext('2d');
canvas.clearRect(0, 0, width, height);
}
Дело за малым - собрать все в один HTML-файл.
Пример работы
Совместимость с броузерами
– IE 6;
– Mozilla Firefox 1.5;
– Opera 9.01+;