Google Map API – chương 3


Trong chương trước , ta đã làm quen với google maps , và change được 1 vài tham số. Nhưng mục tiêu của google maps là liên kết , tương tác được với người dùng .

Để làm được điều đó, lúc này ta cần 5 file : index.php, map_data.php, map_function.js , retrieveMarkers.php và storeMarker.php .

File storeMarker.php chúng ta dùng để lưu thông tin server . File retrieveMarkers.php chúng ta sẽ bàn sau (nó là 1 file về ajax).

Bây giờ , chúng ta cùng xem file sau để hiểu cách tương tác với người dùng : (map_function.js)

function init() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.addControl(new GMap2TypeControl());
map.setCenter(new GLatLng(centerLatitude, centerLongitude), startZoom);
//allow the user to click the map to create a marker
GEvent.addListener(map, "click", function(overlay, latlng) {
var marker = new GMarker(latlng)
map.addOverlay(marker);
});
}
}

Chú ý : trong hàm function(overlay,latlng) ta thấy 2 biến overlay và latlng .
latlng : là biến biểu trưng cho GLatLng , nó xác định tọa độ nơi người dùng click .

Hiển thị info window
Tương tự như hiển thị marker , ta dùng latlng để xác định tọa đổ của hộp info window.

GEvent.addListener(map, "click", function(overlay, latlng) {
map.openInfoWindow (latlng,document.createTextNode("You clicked here!"));
});

Embedding a Form into the Info Window
Khi người dùng muốn tạo new marker , trước tiên , họ cần tìm địa điểm mà họ muốn tạo, cho nên ta cần cho họ hộp text field, để họ dễ dàng link tới địa điểm mà họ muốn :frown:textfield của chúng ta sẽ đưa vào google map qua Dom XML)

<form action="" onsubmit="storeMarker(); return false;">
<fieldset style="width:150px;">
<legend>New Marker</legend>
<label for="found">Found</label>
<input type="text" id="found" style="width:100%;"/>
<label for="left">Left</label>
<input type="text" id="left" style="width:100%;"/>
<input type="submit" value="Save"/>
<input type="hidden" id="longitude"/>
<input type="hidden" id="latitude"/>
</fieldset>
</form>

Tiếp theo ta cần dùng phương thức ajax để lưu lại giá trị và lập trình . Google cung cấp cho ta object GXmlHttp() .

Vậy điều gì sẽ xảy ra khi user click vào button :
– Thông tin người dùng gửi sẽ chuyển đến server và đc server kiểm tra .
– Các thông tin đó sẽ được lưu trữ lại .
– Và server trả về thông tin lên web .

Và đây là thông tin trong file ajax :

function storeMarker(){
var lng = document.getElementById("longitude").value;
var lat = document.getElementById("latitude").value;
var getVars = "?found=" + document.getElementById("found").value
+ "&left=" + document.getElementById("left").value
+ "&lng=" + lng
+ "&lat=" + lat ;
var request = GXmlHttp.create();
//open the request to storeMarker.php on your server
request.open('GET', 'storeMarker.php' + getVars, true);
request.onreadystatechange = function() {
if (request.readyState == 4) {
//the request is complete
var xmlDoc = request.responseXML;
//retrieve the root document element (response)
var responseNode = xmlDoc.documentElement;
//retrieve the type attribute of the node
var type = responseNode.getAttribute("type");
//retrieve the content of the responseNode
var content = responseNode.firstChild.nodeValue;
//check to see if it was an error or success
if(type!='success') {
alert(content);
} else {
//create a new marker and add its info window
var latlng = new GLatLng(parseFloat(lat),parseFloat(lng));
var marker = createMarker(latlng, content);
map.addOverlay(marker);
map.closeInfoWindow();
}
}
}
request.send(null);
return false;
}
function createMarker(latlng, html) {
var marker = new GMarker(latlng);
GEvent.addListener(marker, 'click', function() {
var markerHTML = html;
marker.openInfoWindowHtml(markerHTML);
});
return marker;
}

Đầu tiên ta nhận các giá trị qua phương thức Get và gửi tới storeMarker.php qua “GET” , sau đó , ta dùng responseXML để nhận result từ file .php( tức là file storeMarker.php không trả kết quả về text mà trả kết quả về 1 đối tượng XML ) . Sau đó , từ result này , ta lấy được content bằng dòng :

//retrieve the root document element (response)
var responseNode = xmlDoc.documentElement;
//retrieve the type attribute of the node
var type = responseNode.getAttribute("type");
//retrieve the content of the responseNode
var content = responseNode.firstChild.nodeValue;

Nếu success thì :

//create a new marker and add its info window
var latlng = new GLatLng(parseFloat(lat),parseFloat(lng));
var marker = createMarker(latlng, content);
map.addOverlay(marker);
map.closeInfoWindow();

Và đây là file storeMarker.php :

<?php
header('Content-Type: text/xml');
$lat = (float)$_GET['lat'];
$lng = (float)$_GET['lng'];
$found = $_GET['found'];
$left = $_GET['left'];
//create an XML node
$marker = <<<MARKER
<marker lat="$lat" lng="$lng" found="$found" left="$left"/>\n
MARKER;
//open the data.xml file for appending
$f=@fopen('data.xml', 'a+');
if(!$f) die('<?xml version="1.0"?>
<response type="error"><![CDATA[Could not open data.xml file]]></response>
');
//add the node
$w=@fwrite($f, $marker);
if(!$w) die('<?xml version="1.0"?>
<response type="error"><![CDATA[Could not write to data.xml file]]></response>');
@fclose($f);
//return a response
$newMarkerContent = "<div><b>found </b>$found</div><div><b>left </b>$left</div>";
echo <<<XML
<?xml version="1.0"?>
<response type="success" icon="$icon"><![CDATA[$newMarkerContent]]></response>
XML;
?>

Trong chú thích code, đã ghi rất rõ, tôi chỉ nói lại các đường hướng :
Đầu tiên ta nhận các biến qua phương thức GET , Sau đó tạo file XML , cuối cùng trả về content là XML . và gởi về file Ajax xử lý ( lúc này dĩ nhiên status = 4)

Vậy là chúng ta đã xử lý được trong file ajax , thế khi load lên , làm sao để check trong file XML để load lên cho người dùng xem , những chỗ họ đã check .
Đầu tiên phải load XML lên

var xmlDoc = request.responseXML;
//retrieve the root document element (response)
var responseNode = xmlDoc.documentElement;
//retrieve the type attribute of the node
var type = responseNode.getAttribute("type");
//retrieve the content of the responseNode
var content = responseNode.firstChild.nodeValue;

Sau đó add vào marker và đưa lên info window :

var latlng = new GLatLng(parseFloat(lat),parseFloat(lng));
var marker = createMarker(latlng, content);
map.addOverlay(marker);
map.closeInfoWindow();

Load XML từ ngoài vào
Trường hợp trên , chúng ta load XML khi click vào 1 địa điểm trên google map . Còn trường hợp này , ta có data là file XML sẵn . Chúng ta sẽ load nó vào trong bản đồ chúng ta bằng cách load file XML đó và parse nó vào database .

Load XML trong file retrieveMarkers.php:

<?php
header('Content-Type:text/xml');
$markers = file_get_contents('data.xml');
echo <<<XML
<markers>
$markers
</markers>
XML;
?>

Sử dụng XML (ta sẽ đưa các node XML vào mảng , từ đó xử lý và load, đưa vào google map ):

function retrieveMarkers() {
var request = GXmlHttp.create();
//tell the request where to retrieve data from.
request.open('GET', 'retrieveMarkers.php', true);
//tell the request what to do when the state changes.
request.onreadystatechange = function() {
if (request.readyState == 4) {
var xmlDoc = request.responseXML;
var markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var lng = markers[i].getAttribute("lng");
var lat = markers[i].getAttribute("lat");
//check for lng and lat so MSIE does not error
//on parseFloat of a null value
if(lng && lat) {
var latlng = new GLatLng(parseFloat(lat),parseFloat(lng));
var html = '<div><b>Found</b> '
+ markers[i].getAttribute("found")
+ '</div><div><b>Left</b> '
+ markers[i].getAttribute("left")
+ '</div>';
var marker = createMarker(latlng, html);
map.addOverlay(marker);
}
} //for
} //if
} //function
request.send(null);
}

Và dĩ nhiên , ta phải gọi hàm retrieveMarkers() từ file map_functions.js chứ :

function init() {
... cut ...
map = new GMap2(document.getElementById("map"));
retrieveMarkers();
... cut ...
}

Khi đó kết quả của chúng ta xuất ra sẽ là

<markers>
<marker lat=”37.441″ lng=”-122.141″ found=”Keychain” left=”Book”/>
<marker lat=”37.322″ lng=”-121.213″ found=”Water Bottle” left=”Necklace”/>
… etc …
</markers>

Thêm Image vào Gicon
GIcon là đối tượng ảnh khi ta click vào google maps để đánh dấu điểm , thì nó xuất hiện , biểu tượng mặc định của nó là : .

• GIcon.image: URL of the image
• GIcon.iconSize: Size of the image in pixels
• GIcon.iconAnchor: Location of the anchor point

Vậy để change nó , ta làm thế nào ?

if(iconImage!='') {
var icon = new GIcon();
icon.image = iconImage;
icon.iconSize = new GSize(25, 25);
icon.iconAnchor = new GPoint(14, 25);
icon.infoWindowAnchor = new GPoint(14, 14);
}

Trong đoạn trên iconImage là đường dẫn của icon của chúng ta .

Đó là basic, bây giờ chúng ta sẽ thay trực tiếp icon vào google maps . Tạo form :

inputForm.innerHTML = '<fieldset style="width:150px;">'
+ '<legend>New Marker</legend>'
+ '<label for="found">Found</label>'
+ '<input type="text" id="found" style="width:100%"/>'
+ '<label for="left">Left</label>'
+ '<input type="text" id="left" style="width:100%"/>'
+ '<label for="left">Icon URL</label>'
+ '<input type="text" id="icon" style="width:100%"/>'
+ '<input type="submit" value="Save"/>'
+ '<input type="hidden" id="longitude" value="' + lng + '"/>'
+ '<input type="hidden" id="latitude" value="' + lat + '"/>'
+ '</fieldset>';

Đưa biến vào :

var getVars = "?found=" + document.getElementById("found").value
+ "&left=" + document.getElementById("left").value
+ "&icon=" + document.getElementById("icon").value
+ "&lng=" + lng
+ "&lat=" + lat ;

File retrieveMarkers.php :

$icon = $_GET['icon'];
$marker = <<<MARKER
<marker lat="$lat" lng="$lng" found="$found" left="$left" icon="$icon"/>
MARKER;

Hàm createMarkers()

function createMarker(latlng, html, iconImage) {
if(iconImage!='') {
var icon = new GIcon();
icon.image = iconImage;
icon.iconSize = new GSize(25, 25);
icon.iconAnchor = new GPoint(14, 25);
icon.infoWindowAnchor = new GPoint(14, 14);
var marker = new GMarker(latlng,icon);
} else {
var marker = new GMarker(latlng);
}
GEvent.addListener(marker, 'click', function() {
var markerHTML = html;
marker.openInfoWindowHtml(markerHTML);
});
return marker;
}

Nếu làm đúng , kết quả của chúng ta sẽ thế này :

No comments

Google Map API

Wednesday, 16. December 2009, 03:05:15

Chương 1 :
Trong khi mọi người đã quen với image tĩnh thì google lặng lẽ phát triển google maps từ khi đã hoàn thành gmail . Sau đó , họ đưa lên vệ tinh .
Qua cuốn sách này , chúng ta sẽ trải nghiệm từ thấp-> cao, với các ví dụ từ đơn giản -> phức tạp .
KML: Your First Map
Trong năm 2006, google ra gói support cho file KML . Bạn có thể dễ dàng nhúng URL vào trong search box và google sẽ trỏ tới đó . Chúng ta sẽ không bàn sâu về nó , nhưng chúng ta sẽ thử 1 ví dụ đơn giản để chạy nó .
KML là viết tắt của : Keyhole Markup Language , nó là kết hợp của google code và XML .
Đầu tiên , chúng ta tạo file toronto.kml , và nội dung chúng ta sẽ mượn từ wikipedia . và chúng ta sẽ thấy vị trí chúng qua google maps .

<?xml version="1.0" encoding="UTF-8"?> 
<kml xmlns="http://www.google.com/earth/kml/2"> 
<Document> 
<name>toronto.kml</name> 
<Placemark> <name>CN Tower</name> 
<description>The CN Tower (Canada's National Tower, Canadian National Tower), at 553.33 metres (1,815 ft., 5 inches) is the tallest freestanding structure on land. It is located in the city of Toronto, Ontario, Canada, and is considered the signature icon of the city. The CN Tower attracts close to two million visitors annually. http://en.wikipedia.org/wiki/CN_Tower</description> 
<Point> <coordinates>-79.386864,43.642426</coordinates> </Point> 
</Placemark> 
</Document> 
</kml>

Để thấy kết quả , ta upload file kml lên host , và lên google maps , paste URL đó vào search field . ta sẽ thấy kết quả :
Giới thiệu về Wayfaring.com.
Đây là 1 dịch vụ mà nó sử dụng google api, và nó cho phép người dùng tạo map tại bất cứ nơi nào họ muốn . Chỉ cần 1 account tại website trên , bạn có thể tạo map mà bạn muốn.
Để biết thêm chi tiết, bạn thử tạo add a waypoint và add a route trong đó , sẽ hiểu được các tính năng của site .

Chương 2 : Getting Started
Trong chương này , bạn sẽ học cách tạo project google maps.
The first map :
Trong phần này , bạn sẽ học các google Api key , và sử dụng chúng sau này .
Keying Up : Trước khi bạn tạo google maps application, bạn cần có google maps api key . Để có nó, bạn cần vào http://www.google.com/apis/maps/signup.html để đăng kí nhận google api key , sau đó chúng ta nhận key , key của chúng ta có dạng :
ABQIAAAAGZ-pnGJosgnPUTzQUU-KdBTR2osnlv5EkiJwpolcVjSqqg8kehQFBKfr6wyvj7ol_XRIYBXQTQF1QQ

Sau đó , chúng ta sẽ nhúng key vào domain của chúng ta , code để nhúng vào như sau :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Maps JavaScript API Example</title>
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAGZ-pnGJosgnPUTzQUU-KdBTR2osnlv5EkiJwpolcVjSqqg8kehQFBKfr6wyvj7ol_XRIYBXQTQF1QQ" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
function load() {
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
}
}
//]]>
</script>
</head>
<body onload="load()" onunload="GUnload()">
<div id="map" style="width: 100%; height: 800px"></div>
</body>
</html>

Code trên có 3 điểm cần chú ý :
A) Key = Yourkey . Đó là key mà google cho bạn khi đăng kí .
B) Function load() . Là function gọi google .
C) Div id=”map” . Dù đó là div rỗng nhưng google sẽ dùng nó để gán bản đồ vào .
Chú ý : class GlatLng là lớp rất mạnh với nhiều tính nănng , chúng ta sẽ bàn đến nó sau này .

Specifying a New Location
Đoạn :

map.setCenter(new GLatLng(37.4419, -122.1419), 13);

có tham số 37.4419,-122.1419 là tâm điểm của bản đồ khi load lên . Để có thể xác định vị trí mặc định khi bản đồ load lên , bạn có thể vào http://maps.google.com/ -> gõ địa chỉ bạn muốn vào , sau đó sẽ ra được địa điểm đó , tại URL bạn sẽ thấy 3 tham số , VD : tôi gõ “phú mỹ hưng” vào -> click vào link bên trái, phía trên màn hình -> URL là :

http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=ph%C3%BA+m%E1%BB%B9+h%C6%B0ng&sll=37.0625,-95.677068&sspn=40.324283,107.138672&ie=UTF8&hq=ph%C3%BA+m%E1%BB%B9+h%C6%B0ng&hnear=&radius=15000&ll=10.75557,106.638451&spn=0.093767,0.209255&z=13&iwloc=B

Bạn sẽ thấy ll=10.75557,106.638451 chính là 2 giá trị center . Bạn thay giá trị đó vào link cũ , sẽ thấy khi load bản đồ lên , center mặc định sẽ là phú mỹ hưng .

Separating Code from Content
Để code trở nên dễ thao tác hơn , ta phân code ra làm 3 trang , 1 trang index, 1 trang data, 1 trang js_function . Trong đó trang index là trang chính , nó sẽ gọi các trang js và trang data vào , trang js cung cấp các phương thức , trang data dùng php để load dữ liêu lên . Ta có trang như sau :

Index.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"➥
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=➥
ABQIAAAAfAb2RNhzPaf0W1mtifapBRI9caN7296ZHDcvjSpGbL7PxwkwBS➥
ZidcfOwy4q2EZpjEJx3rc4Lt5Kg" type="text/javascript"></script>
<script src="map_data.php" type="text/javascript"></script>
<script src="map_functions.js" type="text/javascript"></script>
</head>
<body>
<div id="map" style="width: 500px; height: 300px"></div>
</body>
</html>

map_functions.js

var centerLatitude = 37.818361;
var centerLongitude = -122.478032;
var startZoom = 13;
var map;
function init() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
var location = new GLatLng(centerLatitude, centerLongitude);
map.setCenter(location, startZoom);
}
}
window.onload = init;
window.onunload = GUnload;

Basic Interaction
Sau khi bạn đã center được map, bây giờ bạn cần thao tác nhiều hơn thế trên map, đúng không ?
a) Using Map Control Widgets
Google cung cấp 5 control sau, để bạn thao tác :
1) GLargeMapControl : large pan and zoom control .
2) GSmallMapControl : mini pan and zoom control .
3) GScaleControl : độ phóng to .
4) GSmallZoomControl : 2 button zoom của google .
5) GMapTypeControl : cho người dùng chuyển đổi giữa Map, satelite , và hybrid types .

Khi muốn add chúng vào , bạn add thông qua hàm addControl(). Ví dụ , tôi muốn add small map control vào site, tôi dùng hàm :

map.setCenter(new GLatLng(10.75557,106.638451), 13);
// bắt đầu từ đây  
map.addControl(new GSmallMapControl());
map.addControl(new GLargeMapControl());
map.addControl(new GScaleControl());
map.addControl(new GSmallZoomControl());
map.addControl(new GMapTypeControl());

Để xem chi tiết các class này , bạn search code OOP của các class này để tùy biến theo ý mình .

Creating Markers
Add marker để xác định điểm đánh dấu của chúng ta trên bản đồ . Chúng ta chọn :
var marker=new Gmarker(location);
Để xác định điểm ta muốn đánh dấu . (location là vị trí center của bản đổ chúng ta, hoặc điểm nào đó, tùy vào bạn .
Sau đó dùng hàm : addOverlay(marker) để đưa marker vào bản đồ .

function init()
{
    if (GBrowserIsCompatible()) {	
        map = new GMap2(document.getElementById("map"));
        map.addControl(new GSmallMapControl());
        var location = new GLatLng(centerLatitude, centerLongitude);
        map.setCenter(location, startZoom);
        var marker = new GMarker(location)
        map.addOverlay(marker);
    }
}

Sau khi code xong , ta có kết quả như sau :

Opening Info Windows
Và bây giờ, chúng ta sẽ đi đến phần phản hồi người dùng , Khi người dùng click vào marker , chúng ta sẽ phản hồi lại thông tin .
Ở mức độ basic như là xuất ra hộp alert , ta gõ như sau :

GEvent.addListener(marker, 'click',
function() {
alert("You clicked the marker!");
}
);

Khi click vào marker , ta xuất ra dòng “You clicked the marker”.

Để xuất ra thông tin chi tiết của hộp info, ta dùng hàm openInfoWindowHtml() .
VD :

GEvent.addListener(marker, 'click',
function() {
marker.openInfoWindowHtml(description);
}
); 

Và để sử dụng chúng , ta làm như sau :

var centerLatitude = 37.818361;
var centerLongitude = -122.478032;
var description = 'Golden Gate Bridge';
var startZoom = 13;
var map;
// ham add marker
function addMarker(latitude, longitude, description) {
var marker = new GMarker(new GLatLng(latitude, longitude));
GEvent.addListener(marker, 'click',
function() {
marker.openInfoWindowHtml(description);
}
);
map.addOverlay(marker);
}
// ket thuc
function init() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.setCenter(new GLatLng(centerLatitude, centerLongitude), startZoom);
// goi add marker
addMarker(centerLatitude, centerLongitude, description);
// ket thuc goi
}
}
window.onload = init;
window.onunload = GUnload;

A List of Points
Bạn cần nhiều điểm marker , chứ đâu chỉ 1 , phải không ? Để làm được điều đó, chúng ta sẽ sử dụng mảng giá trị .
Và mảng của chúng ta sẽ như thế này :

var myMarker = {
'latitude': 37.818361,
'longitude': -122.478032,
'name': 'Golden Gate Bridge'
};

Và mảng cha , để lưu tất cả các mảng con bên trong, được khai báo như sau :

var myMarkers = [Marker1, Marker2, Marker3, Marker4];

Ví dụ, ta muốn lưu 3 marker, ta gõ như sau :

var markers = [
{
'latitude': 37.818361,
'longitude': -122.478032,
'name': 'Golden Gate Bridge'
},
{
'latitude': 40.6897,
'longitude': -74.0446,
'name': 'Statue of Liberty'
},
{
'latitude': 38.889166,
'longitude': -77.035307,
'name': 'Washington Monument'
}
];

Sau đó, để duyệt mảng , ta dùng hàm :

for (id in markers) {
// create a marker at markers[id].latitude, markers[id].longitude
}

Hàm này sẽ chạy hết tất cả các markers của chúng ta . Cứ mỗi vòng chạy , nó sẽ tạo ra 1 marker trên bản đồ .

Như vậy , tới thời điểm này , ta đã có đủ các hàm để đưa vào . Và ta chạy code cuối cùng trong file map_functions.js

var map;
var centerLatitude = -95.0446;
var centerLongitude = 40.6897;
var startZoom = 3;
function addMarker(longitude, latitude, description) {
var marker = new GMarker(new GLatLng(latitude, longitude));
GEvent.addListener(marker, 'click',
function() {
marker.openInfoWindowHtml(description);
}
);
map.addOverlay(marker);
}
function init() {
if (GBrowserIsCompatible()) {
map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.setCenter(new GLatLng(centerLatitude, centerLongitude), startZoom);
for(id in markers) {
addMarker(markers[id].latitude, markers[id].longitude, markers[id].name);
}
}
}
window.onload = init;
window.onunload = GUnload;

Ghi chú :
-Hàm for(id in markers) { addMarker(markers[id].latitude, markers[id].longitude, markers[id].name); } mỗi lần chạy sẽ gọi hàm addMarker bên trên , và add marker lên màn hình .
– còn markers là data ta phải khai báo trong file data.php . File đó có nội dung giống đoạn khai báo mảng markers phía trên .

Advertisements
%d bloggers like this: