www.gmapsapi.com

Kompleksowy kurs podstaw API, po którym mapowianie nie będzie miało przed Tobą żadnych tajemnic!

Setki przykładów, kursów i poradników z kodem gotowym do skopiowania i korzystania.

Największa strona o Google Maps API w Polsce, największe źródło informacji w języku polskim.

Rysowanie polilinii przez użytkownika

Ten artykuł dotyczy API w wersji 2

« powrót do listy poradników

Google Maps API pozwala na dodawanie na mapę polilinii (z wypełnieniem lub bez). Dodawanie polilinii jest bardzo proste, kosztem dodatkowych trudności przy implementowaniu zaawansowanych rozwiązań, takich jak np. możliwość dodawania i edytowania polilinii przez użytkownika. To skomplikowane zagadnienie będzie tematem niniejszego tutorialu.

Filozofia działania

Każda edytowalna polilinia będzie reprezentowana przez jeden obiekt klasy Linia. Kolekcja wszystkich edytowalnych polilinii, jakie w obecnej chwili są wyświetlane na mapie będzie zebrana w jednej globalnej tablicy linie.

Każdy obiekt linii będzie posiadał następujące właściwości:

  • polilinia - odwołanie do obiektu klasy GPolyline na mapie. Dzięki niemu będzie wiadomo, którą polilinię usunąć z mapy, gdy nastąpi odświeżenie lub dodanie nowego węzła,
  • znaczniki - tablica z elementami klasy Znacznik,
  • markery - tablica z odwołaniami do obiektów klasy GMarker, reprezentującymi węzły polilinii. Dzięki niej będzie wiadomo, które markery usunąć, gdy polilinia zostanie zakończona,
  • kolor,przezroczystosc,grubosc - jak same nazwy mówią. Przykładowe poprawne wartości (kolejno): #ff0000, 0.65, 3.

Obiekty tej klasy powinny mieć zaimplementowaną metodę dodajPunkt(), która doda nowy punkt do tablicy znaczniki, a następnie wywoła metodę narysuj(), która na podstawie tej tablicy usunie starą polilinię i znaczniki, i narysuje ich nowe odpowiedniki.

Własność znaczniki to tablica węzłów, reprezentowanych obiektami klasy Znacznik. Każdy z nich posiada własność punkt, reprezentujący punkt, w którym jest węzeł (obiekt klasy GLatLng).

W globalnej zmiennej rysowana będziemy przechowywać odwołanie do aktualnie rysowanej polilinii (do obiektu klasy Linia), lub jeśli nic nie będzie w danej chwili rysowane ustawimy tą wartość na false. Dzięki tej zmiennej będzie wiadomo, co zrobić w momencie kliknięcia na mapę. Jeśli wartość będzie równa false, to utworzymy nową linię, dodamy do niej punkt, odświeżymy ją i dodamy do tablicy linii, a jeżeli zmienna ta będzie wskazywała na odwołanie, to jedynie dodamy nowy punkt i odświeżymy obrazek.

W globalnej zmiennej kliknieta będzie przechowywane odwołanie do ostatnio klikniętej polilinii (GPolyline). Wartość tą będziemy zmieniać przy kliknięciu na polilinię, o ile zmienna rysowana ustawiona jest na false. Po kliknięciu pokażemy okienko, w którym będą opcje takie jak edycja węzłów, usunięcie polilinii, zmiana koloru itp. Znając ostatnio klikniętą polilinię GPolyline, będzie można za pomocą pętli sprawdzić, któremu obiektowi klasy Linia ona odpowiada. W przypadku zmiany koloru, grubości itp. zmienimy odpowiednią własność polilinii i przerysujemy ją, przypisując zmiennej kliknieta nowe odwołanie do nowego obrazka. W przypadku wyboru edycji węzłów ustawimy odwołanie do tej polilinii jako wartość zmiennej rysowana i odświeżymy ją, by wyświetlić markery.

Uff, to tyle z teorii na temat działania aplikacji. W praktyce będzie nieco gorzej, bo jest jeszcze parę aspektów, które trzeba wziąć pod uwagę.

Praktyka

Na początku zadeklarujemy globalne wartości oraz ikonki (początkowy węzeł, środkowy węzeł i końcowy węzeł):

var mapa;	
var kliknieta;		
var linie=[];
var rysowana = false;

var ikona_start = new GIcon(G_DEFAULT_ICON);
ikona_start.image='http://www.google.com/intl/en_ALL/mapfiles/dd-start.png';

var ikona_koniec = new GIcon(G_DEFAULT_ICON);
ikona_start.image='http://www.google.com/intl/en_ALL/mapfiles/dd-end.png';

var ikona_srodek = new GIcon();
ikona_srodek.image = 'http://maps.google.com/mapfiles/kml/pal4/icon24.png';
ikona_srodek.shadow = '';
ikona_srodek.iconAnchor=new GPoint(16,16);
ikona_srodek.infoWindowAnchor=new GPoint(16,16);
ikona_srodek.shadowSize=new GSize(0,0);
ikona_srodek.iconSize=new GSize(32,32);

Teraz czas na definicję klas Linia i Znacznik:

function Linia(kolor,grubosc,przezroczystosc)
{
	rysowana = this;
	this.znaczniki = [];
	this.kolor = kolor;
	this.grubosc = grubosc;
	this.przezroczystosc = przezroczystosc;
	this.polilinia = false;
	this.markery = [];
}

function Znacznik(punkt)
{
	this.punkt = punkt;
}

Póki co nie jest to nic specjalnego - teraz czas napisać prototypy, które faktycznie będą relizowały pewne działania. Na początku dodanie nowego węzła do polilinii:

Linia.prototype.dodajPunkt = function(pozycja)
{
	var punkt = new Znacznik(pozycja);
	this.znaczniki.push(punkt);
}

Przy dodawaniu punktu warto od razu odświeżyć polilinię. Jest to dość skomplikowana funkcja, poniżej przedstawiam jej najważniejsze kluczowe zagadnienia:

Linia.prototype.narysuj = function(markery)
{
	if(markery!=true)
		markery=false;
	else
		markery=true; // czy funkcja ma rysować markery?
	var punkty=[];
	
	/* w tym miejscu należy usunąć stare znaczniki i polilinię, korzystając z własności markery i polilinia */
	
	for(var i=0; i<this.znaczniki.length; i++)
	{
		punkty.push(this.znaczniki[i].punkt);
		if(markery)
		{
			wstawZnacznik(this,i); // dodanie nowego znacznika
		}
	}
	
	// dodanie nowej polilinii
	var polilinia = new GPolyline(punkty,this.kolor,this.grubosc,this.przezroczystosc);
	this.polilinia = polilinia;
	mapa.addOverlay(polilinia);			
	
	/* w tym miejscu należy napisać obsługę kliknięcia na polilinię w celu wyświetlenia dymka */
}

Dodawanie znacznika jest zrealizowane w oddzielnej funkcji, by prawidłowo przechwytywać kliknięcia i inne zdarzenia:

function wstawZnacznik(polilinia,i)
{
	var ikona;
	// wybór odpowiedniej ikonki
	if(i==0)
		ikona=ikona_start;
	else if(i==polilinia.znaczniki.length-1)
		ikona=ikona_koniec;
	else
		ikona=ikona_srodek;
	
	var marker = new GMarker(polilinia.znaczniki[i].punkt,{icon: ikona, draggable: true});
	marker.znacznik = polilinia.znaczniki[i];
	marker.polilinia = polilinia; // przechowujemy odwołania zarówno do polilinii, jak i do obiektu Znacznika
	
	polilinia.markery.push(marker);
	mapa.addOverlay(marker);
	
	GEvent.addListener(marker,'click',function()
	{
		rysowana.zakoncz(); // kończymy rysowanie polilinii po kliknięciu na znacznik
	});
	
	// po przeciągnięciu znacznika uaktualniamy odpowiedni Znacznik dla tej Linii, oraz przerysowujemy ją (razem z markerami)
	GEvent.addListener(marker,'dragend',function()
	{
		marker.znacznik.punkt = marker.getPoint();
		marker.polilinia.narysuj(true);
	});
}

Zdarzenia

Teraz trochę o zdarzeniach. Na początku zdarzenie kliknięcia na mapę:

GEvent.addListener(mapa,'click',function(o,p)
{
	if(!o)
	{
		if(rysowana == false)
		{
			var linia = new Linia('#00ff00',7,0.5);
			rysowana = linia;
			linie.push(rysowana);
		}
		rysowana.dodajPunkt(p);
		rysowana.narysuj(true);
	}
});

Jeśli nie kliknięto na obiekt, to sprawdzamy, czy w danym momencie rysujemy polilinię. Jeśli tak, to jedynie dodajemy do niej nowy punkt, i przerysowujemy ją. Jeśli nie, to wcześniej tworzymy nowy obiekt linii, ustawiamy ją jako aktywną (rysowana), i dodajemy do tablicy polilinii. Dalej wykonujemy identyczne operacje jak dla dodania punktu do istniejącej linii.

Kliknięcie na polilinię ma spowodować wyświetlenie dymka z możliwością edycji:

GEvent.addListener(polilinia,'click',function(p)
{
	if(rysowana!=false)	return;
	kliknieta = polilinia; // zapisujemy odwołanie, przyda się później
	
	/* w tym miejscu należy napisać kod, otwierający okienko */
});

W okienku mogą znaleźć się linki, po kliknięciu których mają wykonać się funkcje np. edytuj():

function edytuj()
{
	for(var i=0; i<linie.length; i++)
	{
		if(linie[i].polilinia===kliknieta)
		{
			rysowana = linie[i];
			break;
		}
	}
	mapa.closeInfoWindow();
	rysowana.narysuj(true);
}

Najpierw poszukujemy, do którego obiektu klasy Linia przypisana jest polilinia, na którą kliknęliśmy. Następnie zamykamy okienko, i dorysowujemy markery (pierwszy argument true). Na tej samej zasadzie można napisać funkcję usuwającą polilinię:

function usun()
{
	var c = confirm('Czy chcesz usunąć tę polilinię?');
	if(!c) return;
	var nlinie = [];
	for(var i=0; i<linie.length; i++)
	{
		if(linie[i].polilinia!=kliknieta)
			nlinie.push(linie[i]);
	}
	linie = nlinie;
	mapa.removeOverlay(kliknieta);
	kliknieta = false;
	mapa.closeInfoWindow();
}

W przypadku usuwania musimy zadbać, by usunąć element tablicy linie, zawierający odwołanie od usuwanej linii, następnie można ją usunąć, zresetować zmienną kliknieta i zamknąć okienko. Wszystko wykonujemy tylko wtedy, jeśli wcześniej użytkownik zatwierdzi pytanie o usunięcie.

Podsumowanie i przykład

Rysowanie polilinii przez użytkownika, z pełną możliwością edycji jest bardzo trudnym zagadnieniem, jest to prawdopodobnie najbardziej skomplikowany przykład na tej stronie. Powyższe listingi prezentują jedynie fragmenty kodu. Zobacz, jak działa skrypt oraz sprawdź, jak zostały one połączone w tym przykładzie: przykład 1pokaż kod przykładu

Polecane artykuły

Dodaj stronę do ulubionego serwisu społecznościowego

Oto, co najczęściej czytają internauci, którzy przeczytali ten artykuł:

Dodawanie znaczników na mapę

API v2

Kurs podstaw cz. II: Podstawowe informacje na temat wstawiania markerów (znaczników)


Dodawanie markerów przez użytkownika

API v2

Poradnik pokazuje, w jaki sposób stworzyć formularz, pozwalający na dodawanie markerów


Popularne, darmowe ikony dla markerów

API v2

Kurs podstaw cz. IV: Lista darmowych ikon do wykorzystania w Twojej aplikacji mapowej


Kategorie markerów i polilinii

API v2

Stwórz markery/polilinie w kilku kategoriach, a następnie ukrywaj i pokazuj wybrane kategorie