заработок вебмастеру

Advego.ru - система покупки и продажи контента для сайтов, форумов и блогов

суббота, 13 сентября 2008 г.

Интерактивная карта Javascript/CSS

Сразу хочу оговориться, я не претендую на звание знатока Javascript, по этому приведенный код будет возможно немного коряв, но своё предназначение он будет выполнять, плюс я хотел отказаться от использования не корректного атрибута OnMouseOn (не корректного для W3C валидатора конечно).

И так, исходное задание — сделать карту Киева с подсветкой районов при наведении курсора.
Карта у нас будет такого вида (подсвечен Дарницкий район):


Как же сделать подсветку районов не используя флеш или SVG. Первое что мне пришло в голову, просто подогнать div-ы друг на друга,и чтобы у каждого div был свой район в бекграунде. На решение похоже, но районы то не квадратные, и получилось бы накладывание углов друг а друга,из-за чего район бы подсвечивался когда курсор был бы на другом районе — вообщем не красиво. И тогда мне пришла в голову идея, на сколько я думал, которая решит проблему. Есть такая технология, которой раньше частенько любили пользоваться — imagemap (карта ссылок). Если кто не помнит, благодаря карте ссылок, мы могли выделить на картинке область (круг или квадрат) которые будут ссылкой. Первый вопрос который пришёл мне в голову — можно ли делать области, которые будут ссылками, полигонами и есть ли программа, которая поможет мне автоматизировать процесс. Долго искать не пришлось, Adobe Fireworks просто чудесно справляется с такой задачей. И так, я взял свою картинку и спомощью инструмента Polygon Hotspot tool обвёл районы на карте, а потом экспортировал всё это в HTML. Получилась карта, где каждый район является ссылкой.

Карта Киева без подсветки районов
10












Исходный код:

<img name="map_kiev" src="images/map_kiev.gif" width="380" height="282" border="0" id="map_kiev" usemap="#m_map_kiev" alt="" />

<map name="m_map_kiev" id="m_map_kiev">
<area shape="poly" coords="134,98,127,116,130,137,149,139,159,130,151,118,134,98" href="#" alt="10" />
<area shape="poly" coords="231,93,212,110,160,130,150,116,134,98,139,80,138,77,167,77,167,88,177,101,178,108,191,109,194,107,193,103,191,100,190,96,231,79,228,85,231,93" href="#" alt="01" />
<area shape="poly" coords="163,187,175,186,170,179,181,177,183,181,196,182,201,187,208,187,213,185,213,175,216,172,217,166,235,174,243,172,244,157,249,155,259,159,265,147,255,142,255,132,244,123,244,118,233,110,233,96,231,93,213,110,161,131,156,134,158,176,163,187" href="#" alt="02" />
<area shape="poly" coords="136,59,137,77,155,76,168,77,167,88,171,93,175,95,177,98,178,102,179,106,179,108,185,108,189,110,192,108,193,107,193,104,191,101,190,97,190,95,231,79,235,76,240,75,237,67,267,58,261,32,252,26,245,26,241,21,236,20,228,17,221,17,220,23,217,25,217,39,213,40,208,34,200,40,196,40,192,53,168,56,149,50,145,53,149,64,144,63,136,59" href="#" alt="03" />
<area shape="poly" coords="138,84,132,102,124,101,123,97,118,96,117,92,108,86,106,86,106,87,104,88,103,86,100,85,100,83,89,82,88,88,81,89,60,73,59,62,75,56,86,55,97,55,96,59,97,61,97,70,103,80,105,81,110,81,118,89,120,85,125,85,131,85,138,84" href="#" alt="04" />
<area shape="poly" coords="73,83,80,89,88,89,90,83,98,83,100,86,103,86,104,88,106,88,107,87,109,87,111,88,113,91,116,92,117,96,122,96,123,98,123,100,126,102,130,102,131,103,127,116,121,114,117,116,112,111,110,110,105,110,105,107,96,105,85,102,74,101,73,83" href="#" alt="05" />
<area shape="poly" coords="33,42,30,35,37,35,42,40,47,33,48,32,39,25,42,22,62,21,65,24,65,13,105,16,106,20,118,27,118,38,132,48,136,56,138,83,129,85,121,84,119,85,119,89,111,81,105,80,98,73,97,66,96,58,98,54,75,55,58,62,33,42" href="#" alt="Оболонский район" />
<area shape="poly" coords="81,145,86,136,74,114,73,112,81,103,73,102,73,83,59,74,58,62,33,42,32,49,28,50,27,56,22,55,12,66,16,71,14,79,9,82,6,88,9,92,2,105,5,114,1,119,3,127,10,122,14,125,19,119,20,113,31,114,43,115,54,113,58,125,73,143,81,145" href="#" alt="07" />
<area shape="poly" coords="86,153,81,146,87,136,74,116,73,111,81,102,103,107,105,110,110,111,121,120,124,126,125,129,122,128,120,130,122,134,117,136,115,141,111,145,108,144,108,147,102,149,93,155,86,153" href="#" alt="08" />
<area shape="poly" coords="154,281,179,273,178,266,180,266,172,245,169,244,167,233,180,233,181,221,157,176,156,134,148,140,130,138,126,116,120,114,117,116,123,121,125,129,122,128,118,131,122,135,117,136,114,141,111,145,108,144,108,148,102,149,100,153,97,153,93,155,86,153,90,157,85,163,88,169,87,176,95,179,99,175,102,174,107,179,104,181,104,193,112,193,114,194,111,198,117,203,121,201,129,206,129,224,136,228,135,235,138,242,137,247,146,248,154,260,154,281" href="#" alt="09" />
</map>


Дальше я планировал, сделать подсветку путем присваивания стиля элементу area. Но потом вышла загвоздка... какой же стиль ему можно присвоить?
И тогда я решил пойти другим путём. Допустим есть картинка с картой ссылок, а что если менять картинку в зависимости от того на какой area наведён курсор. Я начал развивать эту идею.
И того пришёл к такому варианту:для основы карты ссылок используем прозрачный гиф, его размещаем в блоке у которого бекграундом установлена наша картинка с картой. При наведении на элемент карты меняем класс у блока и изменяем картинку. Для того чтобы не возникало дозагрузок картинок с подсвеченными районами (размер то у них не маленький), решил использовать одну картинку с картами где подсвечен каждый район, и в зависимости от класса у блока менять позиционирование бекграунда. Получилась вот такая картинка (посмотреть пример).
Осталось присвоить каждому area свой id района написать css и javascript .
CSS код:

#kiev{
width:380px;
background:url(images/map_kiev.gif) no-repeat;
}
.mapa{
/* исходное положение */
background-position: 0 0 !important;
}
.obolon{
background-position: 0 -846px !important;
}
.troes4ina{
background-position: -840px 0 !important;
}
.goloseev{
background-position: -420px 0 !important;
}
.darnica{
background-position: -420px -846px !important;
}
.solomenskiy{
background-position: -840px -282px !important;
}
.pe4ersk{
background-position: -420px -282px !important;
}
.dnipro{
background-position: 0 -282px !important;
}
.shev4enko{
background-position: 0 -564px !important;
}
.podol{
background-position: -420px -564px !important;
}
.svetoshin{
background-position: -840px -564px !important;
}


Яваскрипт :
//Функция которая меняет класс у блока с id=kiev
function setclass(a)
{
document.getElementById('kiev').className = a;
}
//При загрузке ищем элементы с ID районов, и при наведении вызываем функцию изменения класса
window.onload = function ()
{
document.getElementById('obolon').onmouseover = function(){setclass('obolon');}
document.getElementById('obolon').onmouseout = function(){setclass('mapa');}
document.getElementById('troes4ina').onmouseover = function(){setclass('troes4ina');}
document.getElementById('troes4ina').onmouseout = function(){setclass('mapa');}
document.getElementById('goloseev').onmouseover = function(){setclass('goloseev');}
document.getElementById('goloseev').onmouseout = function(){setclass('mapa');}
document.getElementById('darnica').onmouseover = function(){setclass('darnica');}
document.getElementById('darnica').onmouseout = function(){setclass('mapa');}
document.getElementById('solomenskiy').onmouseover = function(){setclass('solomenskiy');}
document.getElementById('solomenskiy').onmouseout = function(){setclass('mapa');}
document.getElementById('pe4ersk').onmouseover = function(){setclass('pe4ersk');}
document.getElementById('pe4ersk').onmouseout = function(){setclass('mapa');}
document.getElementById('dnipro').onmouseover = function(){setclass('dnipro');}
document.getElementById('dnipro').onmouseout = function(){setclass('mapa');}
document.getElementById('shev4enko').onmouseover = function(){setclass('shev4enko');}
document.getElementById('shev4enko').onmouseout = function(){setclass('mapa');}
document.getElementById('podol').onmouseover = function(){setclass('podol');}
document.getElementById('podol').onmouseout = function(){setclass('mapa');}
document.getElementById('svetoshin').onmouseover = function(){setclass('svetoshin');}
document.getElementById('svetoshin').onmouseout = function(){setclass('mapa');}
}
// за javascript особо не пинайте, я в нём полный 0


Посмотреть как это всё чудесно работает можно сдесь. Карта с подсветкой районов при наведении курсора. Скачать исходники можно сдесь

9 комментариев:

Анонимный комментирует...

Спасибо! Над подобной задачей ломала голову долго и упорно. До такого решения не дошла...

Анонимный комментирует...

да, круто!

Анонимный комментирует...

насчет кода, кстати, можно весь код заменить, например, на

function setclass(a)
{
document.getElementById('kiev').className = a;

}
window.onload = function ()
{

var aw = new Array
aw = document.getElementsByTagName("area")
var i = 0
while(aw[i])
{
var myid = aw[i].id
aw[i].onmouseover = function(){ setclass(this.id);}
aw[i].onmouseout = function(){setclass('mapa');}
i+=1

}
}

Jman комментирует...

Да сейчас смотрю на свой же код, и понимаю, что сейчас бы я написал бы гораздо лучше :)))

Анонимный комментирует...

пример карты на Ajax с подгрузкой только выделенного фрагмента
http://hural-rb.ru/karta/

Анонимный комментирует...

А как сделал с ajax?

Антон комментирует...

Можно сделать то-же самое без картинок с canvas. Пример: http://davidlynch.org/js/maphilight/docs/demo_usa.html

Анонимный комментирует...

Интерактивная карта на HTML+JavaScript. Карта коттеджного поселка для форума. На самой карте только номера участков, информация об участниках форума в таблице рядом с картой. При наведении мышки на строчку таблицы и сама строчка, и номер участка на карте подсвечивается. При наведении мышки на участок также подсвечиваются и номер на карте, и строка таблицы. Если нужно, таблица автоматически прокручивается, но происходит это с некоторой задержкой, чтобы при проведении мышки по карте, через несколько участков, не прокручивать туда-сюда. Прокрутка происходит только после того, как мышка "остановилась" на интересующем участке (а точнее, задержалась больше чем полсекунды).
http://forum.vzaokskom.ru/maps/limberova-interactive.php

Анонимный комментирует...

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