Access

 MS Access i OpenLayers - znaczniki (markery) na mapie i okienko Popup tzw. dymek.

Znaczniki (markery). Informacyjne okienko Popup tzw. dymek.

Jak pisałem już wcześniej, punkty graficzne i znaczniki (markery) na mapie w przedstawionych wcześniej przykładach, wskazują tylko na konkretny punkt, nie informując dokładniej o charakterze punktu. A powinny po kliknięciu (bądź najechaniu wskaźnikiem myszy) wyświetlić w okienku Popup dane dotyczące punktu na który wskazuje znacznik.

Zdarzenia generowane przez znacznik (marker).

Rejestracja zdarzenia 'mouseover' i zmiana kursora myszy na 'rączkę'

Jednym ze zdarzeń jakie generuje znacznik, a które powinniśmy obsłużyć, jest zdarzenie 'mouseover'. Zachodzi ono, gdy kursor myszy znajduje się nad markerem. Po najechaniu kursorem myszy nad prostokątny obszar znacznika, powinniśmy zmienić kursor myszy na 'pointer'   Kursor myszy Pointer

...
// funkcja tworząca pojedyncze punkty graficzne w warstwie wektorowej 'layerMarkers'
// o atrybutach określonych w argumentach funkcji
	function createMarkers(id, lon, lat, markerFile, markerWidth, markerHeight,
												offsetX, offsetY, popupHtml) {
...
	// // utwórz znacznik (marker)
	var marker = feature.createMarker();
...

	// rejestrowanie zdarzenia 'mouseover' nad znacznikiem
	marker.events.register('mouseover', marker,  function(evt){
			feature.layer.div.style.cursor = "pointer";
			OpenLayers.Event.stop(evt);
	});
 

Rejestracja zdarzenia 'click' i utworzenie okna popup

Innym zdarzeniem jakie generuje znacznik, a które powinniśmy obsłużyć, jest zdarzenie 'click'. Zachodzi ono, gdy kursor myszy znajduje się nad markerem i równocześnie zostaje wciśnięty i puszczony prawy przycisk myszy.

...
// funkcja tworząca pojedyncze punkty graficzne w warstwie wektorowej 'layerMarkers'
// o atrybutach określonych w argumentach funkcji
	function createMarkers(id, lon, lat, markerFile, markerWidth, markerHeight,
												offsetX, offsetY, popupHtml) {
...
	// // utwórz znacznik (marker)
	var marker = feature.createMarker();
...

// rejestrowanie zdarzenie kliknięcia znacznika
marker.events.register("click", marker, function(evt){

	popup = new OpenLayers.Popup.FramedCloud(
															id = 'myFramedCloud',
															lonlat = marker.lonlat,
															contentSize = new OpenLayers.Size(0, 0),
															contentHTML = popupHtml,
															anchor = null, //marker.icon,
															closeBox = true);
	// dla exclusive = true, zamykane są inne otwarte okna popup
	map.addPopup(popup, exclusive = true);
	OpenLayers.Event.stop(evt);
});
 
Znaczniki - okna popup
1. Znaczniki i okienka popup (dymki)
Znak Informacja dodatkowa Pliki znaczników graficznych pobrano ze strony
www.icons-land.com

Jak uatrakcyjnić okienka popup (dymki)

Okienka popup wyglądają dość biednie. Ale można zawartość okienka nieco upiększyć. Można dla każdego okienka przekazać w argumencie popupHtml funkcji createMarkers(...) przekazać HTML, tak by umieścić zawartość okienka popup w znaczniku <div id="frameCloud">, w którym umieścimy inne znaczniki. Wszystkim elementom nadamy styl, tak by zawartość okienka popup odpowiadała naszym wymogom (lub zleceniodawcy ).

popupHtml=''
	popupHtml+='<div style="width:150px; border:3px double #080; padding:5px;">'
	popupHtml+='<h1 style="font-size: .8em; color:#008; text-align:center; font-weight:bold;'
	popupHtml+='border-bottom:1px solid #080; margin:0;">Miejsce 02.</h1>'
	popupHtml+='<span style="display:block; font-size:.8em; color:#800; margin: 5px 0; line-height:.9em;">'
	popupHtml+='To jest jeszcze ciekawsze miejsce, które powinieneś zobaczyć.</span>'
	popupHtml+='<div style="text-align:center; font-size:.7em; color:#008;"> '
	popupHtml+='<img style="width:140px; border:3px double #ccc;" src="foto/02_thm.jpg" alt="Foto 2"/><br>'
	popupHtml+='fot.2 Jezioro Dąbrowskie'
	popupHtml+='</div></div>'
 
Styl okna popup
2. Nowy styl okienka popup (dymku)

Styl dla wszystkich elementów widocznego powyżej okienka popup zawiera prawie 700 znaków. Jest to nieco za dużo i ponadto nie ma potrzeby przekazywania takiego samego stylu dla każdej instancji okienka popup. Aby sobie ułatwić kontrolę nad stylem okna popup  utworzymy wewnętrzny arkusz stylów, który umieścimy w części nagłówkowej (pomiędzy znacznikami <head> ...  </head>) wyświetlanej strony.

<head>
	...
	<style type="text/css">
	#frameCloud {width:150px; border:3px double #080; padding:5px;}
	#frameCloud h1{
		font-size:.8em; color:#008; text-align:center; font-weight:bold;
		border-bottom:1px solid #080; margin:0;
	}
	#frameCloud span#dscr{display:block; font-size:.8em; color:#800; margin: 5px 0; line-height:.9em;}
	#frameCloud div#foto{font-size:.7em; color:#008; text-align:center;}
	#frameCloud div#foto img{width:140px; border:3px double #ccc;}
	</style>
	...
</head>
 

Po takich zmianach, musimy dostosować funkcję createMarkers(...) tak, by można było w argumentach przekazać tytuł (popupTitle), opis wskazywanego miejsca (popupDescription), ścieżkę do pliku graficznego (popupImage) oraz podpis pod fotografią (popupImageCaption).

// deklaracja warstwy wektorowej zawierającej znaczniki (markery)
var layerMarkers;
// deklaracja tablicy zawierającej wszystkie markery (ToDo)
var arrMarkers = [];

// utwórz warstwę na przyjęcie znaczników (markerów)
function createMarkersLayer(id, layerName, displayInLayerSwitcher, setVisibility){
	layerMarkers = new OpenLayers.Layer.Markers(layerName);
	// przypisz identyfikator warstwy
	layerMarkers.id = id;
	// pokaż warstwę w oknie przełącznika warstw
	layerMarkers.displayInLayerSwitcher = displayInLayerSwitcher;
	// pokaż warstwę na mapie
	layerMarkers.setVisibility(setVisibility);
}

// funkcja tworząca pojedyncze znaczniki w warstwie wektorowej 'layerMarkers'
// o atrybutach określonych w argumentach funkcji
function createMarkers(id, lon, lat, markerFile, markerWidth, markerHeight, offsetX, offsetY,
												popupTitle, popupDescription, popupImage, popupImageCaption) {

	// konwertuj współrzędne geograficzne z układu odniesienia EPSG:4326 na EPSG:900913,
	var lonLat = new OpenLayers.LonLat(lon, lat).transform(epsg4326, epsg900913);
	// utwórz reprezentuję pary szerokość / wysokość
	var size = new OpenLayers.Size(markerWidth, markerHeight);
	// oblicz przesunięcie markera
	var offset = new OpenLayers.Pixel(offsetX, offsetY);
	// utwórz grafikę w oparciu o adres URL, o rozmiarze (size)
	// i przesunięciu punktu środkowego (offset))
	var icon = new OpenLayers.Icon(markerFile,size, offset);

	// utwórz klasę feature na podstawie danych geograficznych i graficznych
	var feature = new OpenLayers.Feature(layerMarkers, lonLat, {'icon': icon});
	// utwórz klasę 'popupClass', która będzie używana do tworzenia instancji nowego okna popup.
	feature.popupClass = OpenLayers.Class(OpenLayers.Popup.Anchored, {'autoSize': true});

	// utwórz znacznik (marker)
	var marker = feature.createMarker();
	// przypisz identyfikator znacznikowi
	marker.id = id;
	//identyfikator płaszczyzny (ToDo)
	marker.PlaneID = id;

	// rejestrowanie zdarzenie kliknięcia znacznika
	marker.events.register("click", marker, function(evt){

	var popupHtml=''
		popupHtml+='<div id="frameCloud">'
		popupHtml+='<h1>'+popupTitle+'</h1>'
		popupHtml+='<span id="dscr">'+popupDescription+'</span>'
		popupHtml+='<div id="foto">'
		popupHtml+='<img src="'+popupImage+'" alt="foto '+popupTitle+'"/><br>'
		popupHtml+='<span>'+popupImageCaption+'</span>'
		popupHtml+='</div></div>'
	/*
		Definicja okna popup, które będzie utworzone po kliknięciu znacznika.
			• id						- identyfikator okna popup
			• lonlat				- położenie znacznika
			• contentHTML		- pełny tekst HTML określający styl i treść w oknie popup (dymku)
			• contentSize		- nie wiem co to jest
			• anchor				- obiekt, do którego zostanie zakotwiczone okno popup.
												• w MS Access dla anchor = null i plików graficznych "Centered" dymek
													otwiera się dokładnie w punkcie lonlat znacznika
													(po uwzględnieniu offsetX, offsetY), dla anchor = marker.icon
													okienko popup otwiera się na krawędzi znacznika,
												• w FireFox dla anchor = null okno popup otwiera się za pierwszym razem
													w zbyt małym rozmiarze (z paskami przewijania), dla anchor = marker.icon
													okno popup otwiera się prawidłowo.
			• closeBox 			- dla wartości true tworzony jest przycisk 'X' zamykający okno popup
		*/
		//var anchor = {'size': new OpenLayers.Size(0,0), 'offset': new OpenLayers.Pixel(-24, -24)};
		popup = new OpenLayers.Popup.FramedCloud(
																id = 'myFramedCloud',
																lonlat = marker.lonlat,
																contentSize = new OpenLayers.Size(0, 0),
																contentHTML = popupHtml,
																anchor = null, //marker.icon,
																closeBox = true);
		// dla exclusive = true, zamykane są inne otwarte okna popup
		map.addPopup(popup, exclusive = true);
		OpenLayers.Event.stop(evt);
	});

	// rejestrowanie zdarzenia 'mouseover' nad znacznikiem
	// zmiana kursora myszy na 'rączkę'
	marker.events.register('mouseover', marker,  function(evt){
			feature.layer.div.style.cursor = "pointer";
			OpenLayers.Event.stop(evt);
	});

		// dodaj znacznik do warstwy
		layerMarkers.addMarker(marker);
		// dodaj znacznik do tablicy (ToDo)
		arrMarkers.push(marker);
		// dodaj warstwę znaczników do instancji mapy
		map.addLayer(layerMarkers);
	}
 
Styl okna popup
3. Trzy okna popup na mapie
function fDrawMarkers(){
	// utwórz warstwę na przyjęcie znaczników (markerów)
	createMarkersLayer('dymki','Popup (dymki)', true, true)
	// współrzędne punktu
	var lon; var lat;
	// wielkość pliku graficznego i zarazem podkatalog plików graficznych
	var size=48;

	// ścieżka do plików graficznych "Centered")
	var path='markers/IconsLand/PNG/Centered/'+size.toString()+'x'+size.toString()+'/';

	lat="51.30728";lon="22.50085"
	createMarkers('miejsce01',lon,lat, path+'MapMarker_Ball_Right_Pink.png',
										size, size, -size/2, -size,
										'Miejsce 01.',
										'To jest bardzo ciekawe miejsce, które należy odwiedzić.',
										'foto/01_thm.jpg',
										'fot.1 Pola i łąki')

	lat="51.3072";lon="22.49070"
	createMarkers('miejsce02',lon,lat, path+'MapMarker_Board_Pink.png',
										size, size, -size/2, -size,
										'Miejsce 02.',
										'To jest jeszcze ciekawsze miejsce, które powinieneś zobaczyć.',
										'foto/02_thm.jpg',
										'fot.2 Kwitnące drzewo')

	// ścieżka do plików graficznych "NotCentered")
	path='markers/IconsLand/PNG/NotCentered/'+size.toString()+'x'+size.toString()+'/';

	lat="51.289822971448302";lon="22.501583006232977"
	createMarkers('miejsce03',lon,lat, path+'MapMarker_PushPin1_Right_Pink.png',
										size, size, -size/4, -size,
									'Miejsce 03.',
									'To jest najciekawsze miejsce, które bezwzględnie należy odwiedzić.',
									'foto/03_thm.jpg',
									'fot.3 Stara chata')
	// wycentruj mapę w/m współrzędnych środka, powiększ do skali zoomLevel
	fInitCenterMap(22.501000, 51.297918, 14);
}
 
Znak Informacja dodatkowa Pewnym ograniczeniem w stosowaniu znaczników jest sztywno ustalona w wewnętrznym arkuszu stylów szerokość fotografii na '140px'. O ile w oknach popup wyświetlane będą tylko fotografie poziome, okienko wygląda dobrze. Dla fotografii o orientacji pionowej, fotografia jest moim zdaniem zbyt duża (za wysoka). Optymalną wysokością fotografii jest ok. 100 pikseli. Ale by uzyskać taki efekt, powinniśmy w funkcji createMarkers(...) przekazać w dodatkowym argumencie informację o orientacji fotografii i nadać jej odpowiedni styl.
Na razie zostawiam tak, jak jest. Być może uzupełnię kod w najbliższym czasie. (ToDo...)