Активный imagemapping на jQuery

Главная проблема стандартного способа создания карт в том, что тэг <area> не поддерживает никаких css свойств, т.е. при наведении курсором на активную область нельзя никак её подсветить. В этом случае Flash выигрывает (пример карты на flash реализован в проекте pludmales9.lv).

Я предлагаю такой вариант: подсвечиваются не сами активные области, а какие-то картинки расположенные по центру активной области. Это могут быть кружочки, квадратики, и любые другие shape’ы. Проблема заключается в том, что если мы попробуем получить координаты <area> через offsetLeft и offsetTop, то будут возвращаться координаты всей картинки.

Слегка улучшить положение я предлагаю используя библиотеку jQuery (на голом JavaScript тоже можно написать, только дольше и больше). С её помощью найду все элементы <area>, узнаю координаты каждого из атрибута coords и найду среднее значение, размещу картинку по центру каждой области и добавлю события onmouseover и onmouseout, чтобы картинка менялась.

За дело!

Итак, чтобы сделать активный imagemapping подобного плана участков средствами javascript нужно:

  1. Взять картинку на которой будут размечены активные области;
  2. Разметить области с помощью визуальных инструментов (если конечно вы не фанат ручной разметки и вам некуда девать своё время)
  3. В итоге получим код такого плана:

    My Image Map ................................................................................................

    Чтобы можно было менять кружочек в зависимости от того, продан ли участок или нет, добавляем каждому href значение #id1, #id2, #id3 и т. д., а class=”free” и class=”sold” будут указывать на то, продан ли участок или нет.

  4. Рисуем картинки такого плана:

    показывать будем верхнюю половину, а при наведении — вторую.
  5. Для этих кружочков напишем CSS:
    .overblock{
    	width: 22px; /* это зависит от размера картинки */
    	height: 22px; /* высоту ставим в половину меньше */
    	position: absolute; /* естественно */
    	overflow: hidden; /* фикс бага в IE7, а может надо было line-height маленький поставить */
    	cursor: pointer; /* в IE не меняется курсор — исправляем */
    	text-align: center;
    	font: normal 11px sans-serif;
    }
    /* эти два класса создаём специально чтобы было удобно указывать, какой участок продан а какой — нет. */
    div.free{
    	background: url(images/r_free.gif) no-repeat top;
    }
    div.sold{
    	background: url(images/r_bought.gif) no-repeat top;
    }
    /* добавляем класс, который будет изменять кружочек при наведении на активную область */
    div.selected{
    	background-position: bottom;
    }

Подготовительные работы закончились, теперь самое интересное

jQuery

Для получения точных координат самой карты, нам нужно подключить расширение Dimensions (версии 1.1.2). Код, естественно будем писать отдельным файлом чтоб не засорять html.

1. Сначала напишем функцию add_numbers(), которая каждому элементу <area> добавит кружочек

function add_numbers(){
	$("area").each(
		function(){
			var mappos = {};
			// получаем координаты самой карты, здесь используется функция position расширения Dimensions
			$("#map").position(mappos);
			var id = $(this).attr("href").substring(1); // получаем id активной области обрезая #
			var coords = $(this).attr("coords").split(","); // записываем координаты в массив
			// поскольку координаты в атрибуте coords перечисляются поочерёдно (X1, Y1, X2, Y2...),
			// то нам нужно разделить иксы и игреки
			var max_l = 0, min_l = 9999, max_t = 0, min_t = 9999;
			for(i=0; i Number(coords[i]))?Number(coords[i]):min_l;
				}
				else {
					max_t = (max_t < Number(coords[i]))?Number(coords[i]):max_t;
					min_t = (min_t > Number(coords[i]))?Number(coords[i]):min_t;
				}
			}
			// создаём переменные отвечающие за координаты кружочка,
			// записываем туда среднее значение координат
			// добавляем координаты самой карты и отнимаем половину размера кружочка
			var left = Math.floor((max_l+min_l)/2) + mappos["left"] - 11;
			var top = Math.floor((max_t+min_t)/2) + mappos["top"] - 11;
			// помещаем кружочек в документ, добавляем класс текущей активной области (free, sold)
			// прописываем id (хотя может это и лишнее) и записываем в кружочек номер участка
			var div = '
' + id.substring(2) + "
" $("body").append(div) $("#num_" + id).css({ "left": left, "top": top }); // прописываем координаты кружочку // добавляем события при наведении мышки на кружочек $("#num_" + id).hover( function () { add_highlight(id); }, function () { remove_highlight(id); } ); } ); }

2. Дополнительные функции

Пишем две очень простые функции добавления подсветки кружочкам

function add_highlight(id){
	$("#num_" + id).addClass("selected");
}
function remove_highlight(id){
	$("#num_" + id).removeClass("selected");
}

Запуск документа. Добавление событий каждому <area>

$(document).ready(
	function() {
		add_numbers(); // запускаем описанную выше функцию
		// каждому area добавляем событие rollover'а в котором добавляем подсветку кружочку
		// при наведении на всю область, а не только на кружочек
		$("area").hover(
			function () {
				var id = $(this).attr("href").substring(1);
				add_highlight(id);
			},
			function () {
				var id = $(this).attr("href").substring(1);
				remove_highlight(id);
			}
		);
	}
)

Как видите, пришлось продублировать подсветку кружочка, при наведении на область и при наведении на сам кружочек.

Изменение размеров окна

Если у нас центрированная фиксированная вёрстка, то при изменении размеров окна кружочки сдвигаются. Чтобы этого не было, придётся дописать одну функцию удаляющую все кружочки, а так же написать событие resize в котором запустим функцию удаления кружочков и добавления их заново. Конечно это форменное читерство, но мне было лень переписывать получение координат <area> и добавление координат кружочкам в отдельную функцию. Поэтому я сделал так:

// функция удаления кружочков
function remove_numbers(){
	$("div[class*='overblock']").each(
		function() {
			$(this).remove();
		}
	);
}
// при изменении размеров окна удаляем и добавляем кружочки заново
$(window).resize(function(){
	remove_numbers();
	add_numbers();
});

Минусы

  • При изменении размеров окна передобавление кружочков тормозит в IE.
  • Подсвечивается не вся область, а только кружочки

Функциональность можно расширить, например добавить подсветку данных в таблице, это сделано на Jaunsapņi.

Альтернативный вариант imagemapping’а предлагает CSSPlay, сделать карту с помощью CSS, но там все координаты пишутся вручную и области могут быть только прямоугольными.

Исправляем и упрощаем в следующем посте.

Дата: 06.12.2007
»
Категории: JavaScript
Google     

]]> Ivan A-R ]]>

м-м-м… А тебя можно переодически теребить на тему вопросов по jquery? =) Хотя я вроде и сам её уже неплохо запинал =)

»

]]> Никита ]]>

Я в jQuery не спец, поскольку много не писал на нём, но вопросы задавай, возможно смогу помочь, или кто-нибудь другой ответит.

»

]]> Mr.SergE ]]>

Uhh. Būtu dikti priecīgs, ja es spētu tik daudz rindiņas no JavaScript saprast. Bet ne par to ir šis stāsts.
Tīri no dizaina viedokļa tu esi ļoti neveiksmīgi realizējis to karti lapā, ko taisi par piemēru šim kodējumam.
Problēma slēpjas iekš fakta, ka ja es paņemu, piemēram, adresi Sniegu 7, tad man nav ne jausmas, kur viņa atrodas kartē (skatoties uz mana laptopa ar 1024×768 izšķirtspēju). Tas pats attiecās uz karti, ja es tajā uzbraucu augšējā daļā uz cipariem kartē — no 28 līdz 48 uzbraucot virsū, man nav ne jausmas, kur man sarakstā tas parādās, jo ekrānā es to neredzu.

»

]]> Никита ]]>

Mr.SergE, да есть такая проблема. Ну значит владельцы маленьких мониторов будут искать участок по Id. Компактнее эту таблицу не сделать. Придётся им больше скроллить.

»

]]> SHAman ]]>

Хочу рабочий пример ^_^

Вообще, статья интересная. Подход оригинальный. Мозг размялся, за что спасибо. Люблю jQuery! Как познакомился – на чистом JS больше не пишу)

»

]]> Никита ]]>

Ну вообще-то рабочий пример на http://jaunsapni.merapi.lv
Но если хочется ссылку “скачать”, тогда сделаю отдельно.

»

]]> SHAman ]]>

Да, хотелось бы… Если можно. Тупой примитивный пример, где только это и ничего лишнего.

»

]]> Игорь ]]>

Ты видел, что происходит с твоими кружочками при ресайзе в Опере? Я не понимаю, зачем ты в данном случае использовал position: absolute, когда с position: relative всё прекрасно можно сделать, и не придется через *опу обрабатывать ресайз окна. Это конечно немного не то, но всё же: http://www.oket.lv/lat/houses

»

]]> Никита ]]>

Блин! Точно! Что ж я сразу-то не догнал?! Уже переделал. Сейчас напишу новый пост.

»

]]> Seleckis.lv :: журнал Никиты Селецкого » » JS-Imagemapping — исправленно. ]]>

[...] — исправленно. В предыдущем посте я написал как делается активный imagemapping на [...]

»

]]> Игорь ]]>

Оперативно :)

»

]]> Максим Покровский ]]>

Да, jQUERY действительно хорошая штучка. В который раз убеждаюсь.

»

]]> flash переделать в gif « Эхо блогосферы ]]>

[...] Никита пишет: В этом случае Flash выигрывает (пример карты на flash реализован в проекте pludmales9.lv). Я предлагаю такой вариант: подсвечиваются не сами активные области, а какие-то картинки расположенные по центру активной области. … div.free{ background: url(images/r_free.gif) no-repeat top; } div.sold{ background: url(images/r_bought.gif) no-repeat top; } /* добавляем класс, который будет изменять кружочек при наведении на активную область */ div.selected{ background-position: … [...]

»

Напишите комментарий