Friday, January 27, 2012, 15:46

Google Maps API, JSON, dan jQuery?

Apa kabar dunia? Hari ini saya akan berbagi tutorial tentang implementasi Google Maps API sederhana untuk prototype sistem informasi Warung Pecel dengan bantuan JSON dan jQuery.

Untuk melihat hasil akhir yang dijelaskan pada tutorial ini, silakan melihat pada link berikut ini.

Peta warung pecel tersebut pada dasarnya akan menampilkan warung-warung yang sedang buka. Informasi detail setiap warung disimpan dalam satu file JSON untuk kemudian ditampilkan sebagai infoWindow pada map.

Markup

Terlebih dahulu kita siapkan markup untuk canvas map yang akan ditampilkan.

<div id="map_canvas"></div>


Kemudian buat satu panel yang akan menampung daftar warung dan map controller.

<div id="map-panel" class="visible clearfix">
<div class="mp-content">
<div id="map-options" class="clearfix">

Map Option:
<ul>
<li>
  <a id="toggle-traffic" href="#"><em class="i-showtr"> </em><span>Show Traffic</span></a>
</li>
<li><a id="map-view" href="#">Map View</a></li>
<li><a id="sat-view" href="#">Satellite View</a></li>
</ul>
</div>
<div id="foodmap-ft-list">
<ul class="ft-list clearfix">
<li>
  <a class="ft-ftimg" href="#"><img src="img/uploads/ava_1.jpg" alt="" /></a>
  <a href="#">Warung Pecel Mbok Birah</a>
  <span class="ft-adr">Bangsri, Purwantoro</span>
  <span class="ft-status"><em class="msmall-on"> </em></span>
</li>
<li class="even">
   <a class="ft-ftimg" href="#"><img src="img/uploads/ava_2.jpg" alt="" /></a>
   <a href="#">Warung Pecel Yu Painem</a>
   <span class="ft-adr">Ndangkrang, Purwantoro</span>
   <span class="ft-status"><em class="msmall-on"> </em></span>
</li>
</ul>
</div>
</div>

<!--.mp-content-->
    <a class="mp-toggle" href="#"><em class="arr-close"></em></a>
  </div>


Map options berisi tombol-tombol untuk mengatur tampilan peta, seperti menampilkan traffic layer, dan pilihan map maupun satellite view.

<div id="map-options" class="clearfix">

Map Option:
<ul>
<li>
  <a id="toggle-traffic" href="#"><em class="i-showtr"></em><span>Show Traffic</span></a>
</li>
<li><a id="map-view" href="#">Map View</a></li>
<li><a id="sat-view" href="#">Satellite View</a></li>
</ul>
</div>


Foodmap List akan menampung daftar-daftar warung yang ingin ditampilkan.

<div id="foodmap-ft-list">
<ul class="ft-list clearfix">
<li>
  <a class="ft-ftimg" href="#"><img src="img/uploads/ava_1.jpg" alt="" /></a>
  <a href="#">Warung Pecel Mbok Birah</a>
  <span class="ft-adr">Bangsri, Purwantoro</span>
  <span class="ft-status"><em class="msmall-on"> </em></span>
</li>
<li class="even">
  <a class="ft-ftimg" href="#"><img src="img/uploads/ava_2.jpg" alt="" /></a>
  <a href="#">Warung Pecel Yu Painem</a>
  <span class="ft-adr">Ndangkrang, Purwantoro</span>
  <span class="ft-status"><em class="msmall-on"> </em></span>
</li>
</ul>
</div>


Link .mp-toggle akan digunakan sebagai toggle untuk menyembunyikan/menampilkan panel.

<a class="mp-toggle" href="#"><em class="arr-close"></em></a>


Kita juga akan membutuhkan beberapa plugin seperti jScrollPane untuk kustomisasi scrollbar, jQuery Tweet, dan yang paling penting adalah script untuk Google Maps API, dan Infobox untuk kustomisasi infowindow. Anda bisa juga menggunakan plugin Marker Clusterer untuk ‘merapikan’ tampilan marker pada map nantinya.

<script src="js/mylibs/jquery.tweet.js" type="text/javascript"><!--mce:0--></script>
<script src="js/mylibs/jScrollPane.js"></script>
<script src="js/mylibs/jquery.mousewheel.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="js/mylibs/infobox.js"></script>
<script src="js/mylibs/markerclusterer_packed.js"></script>



JSON

Persiapkan data item-item yang ingin ditampilkan pada map dengan format JSON, seperti di bawah ini:

[{<br />
  "fId":"1",<br />
  "fName":"Warung Pecel Mbok Birah",<br />
  "latlng":"-7.850543,111.254339",<br />
  "fWeb":"http://www.example.com",<br />
  "fEmail":"[email protected]",<br />
  "fOpenToday":"08:00 - 15:00",<br />
  "fPhone":"0273 415 341",<br />
  "fTwitter":"google",<br />
  "fAvaPath":"ava_1.jpg",<br />
  "fImgPath":"pecel_1.jpg",<br />
  "fAdr":"Bangsri, Purwantoro"<br />
}]


Javascript

Buat fungsi-fungsi yang diperlukan sebagai callback.
Fungsi di bawah ini akan digunakan sebagai callback pada infobox yang akan kita buat nanti, dan juga akan dipanggil setelah map selesai dimuat. Berguna untuk mengambil tweet-tweet terbaru dan menjalankan fungsi tabbed contents untuk infobox.

function ibCallbacks(){
  $(".tweets").each(function(){
    var username = $(this).attr("title");
    $(this).empty().tweet({username: username,count: 3,loading_text: "loading tweets...",template: "{text}  {time}"});
  })
  $(".iw-body").myTabs({hidewhat:".iw-body-main",controller:".iw-body-tabs a"});
}


Untuk menampilkan map, kita bisa membuatnya dalam sebuah fungsi. Pada contoh ini saya membuat satu fungsi baru yaitu initisialize(). Di dalam fungsi tersebut pertama kita masukan variabel dan options untuk map kita.

var g = google.maps;
var myLatLng = new g.LatLng(-7.850543,111.254339);
var myOptions = {
  zoom: 15,
  center: myLatLng,
  mapTypeId: g.MapTypeId.ROADMAP,
  mapTypeControl: false,
  navigationControlOptions: {
  position: g.ControlPosition.RIGHT_CENTER,
  style: google.maps.NavigationControlStyle.SMALL
  }
var map = new g.Map($("#map_canvas")[0],myOptions)

var image = 'img/marker.png';
var shadow = 'img/shadow.png';
var iconmark = new g.MarkerImage(image, new g.Size(32, 40));
var shadowmark = new g.MarkerImage(shadow, new g.Size(29, 25),new g.Point(0,0),new g.Point(5, 25));


Tentukan default center map saat load pertama kali.

var myLatLng = new g.LatLng(-7.850543,111.254339);


Untuk memuat map baru dengan opsi-opsi yang telah ditentukan, Anda menggunakan fungsi google.maps.Map()

var myOptions = {
  zoom: 15,
  center: myLatLng,
  mapTypeId: g.MapTypeId.ROADMAP,
  mapTypeControl: false,
  navigationControlOptions: {
  position: g.ControlPosition.RIGHT_CENTER,
  style: google.maps.NavigationControlStyle.SMALL
  }
var map = new g.Map($("#map_canvas")[0],myOptions);


Variabel-variable untuk kustomisasi marker.

var image = 'img/marker.png';
var shadow = 'img/shadow.png';
var iconmark = new g.MarkerImage(image, new g.Size(32, 40));
var shadowmark = new g.MarkerImage(shadow, new g.Size(29, 25),new g.Point(0,0),new g.Point(5, 25));


Membaca file json yang berisi data warung dengan fungsi getJSON.

$.getJSON('pecel.json', function(data){});


Kemudian, pada callback fungsi di atas kelola data dengan loop dan membuat marker secara otomatis sesuai data yang ada.

Loop Marker & Infobox

var newMarkers = [],marker,clatlng = [];
for (var i = 0; i < data.length; i++){
if (data[i].latlng != null){
  var strlatlng = data[i].latlng,
  fId = data[i].fId,
  fName = data[i].fName,
  fWeb = data[i].fWeb,
  fOpenStat = data[i].fOpenStat,
  fEmail = data[i].fEmail,
  fOpenToday = data[i].fOpenToday,
  fPhone = data[i].fPhone,
  fTwitter = data[i].fTwitter,
  fAdr = data[i].fAdr,
  fAvaPath = (data[i].fAvaPath=='')?'':'<img src="img/uploads/'+data[i].fAvaPath+'" />',
  fImgPath = (data[i].fImgPath=='')?'':'<img src="img/uploads/'+data[i].fImgPath+'" />';

  if (strlatlng.indexOf(',') > 0){
  var arrlatlng = strlatlng.split(',');
  var latlng = new g.LatLng(parseFloat(arrlatlng[0]),parseFloat(arrlatlng[1]));
  marker = new g.Marker({map: map, position: latlng,icon: iconmark,shadow: shadowmark,clickable: true});
  newMarkers.push(marker);
  clatlng.push(latlng);

  /** Infobox **/
var boxText = document.createElement("div");
var boxContent = '<div class="iw-wrap"> <div class="iw-content"> <div class="iw-head clearfix"> <div class="ftd-org"> <a href="#" class="ftd-ftimg">'+fAvaPath+'</a> <div class="ftd-data vcard"> <p class="org">'+fName+'</p> <p class="adr"><span class="street-address">'+fAdr+'</span></p> <div class="ftd-tools"> <ul class="clearfix"> <li><a href="'+fWeb+'"><i class="i-web"></i>Visit Website</a></li><li><a href="#" class="keep-centered" data-index="'+i+'"><i class="i-centered"></i>Keep Centered</a></li> </ul> </div> </div> </div> </div> <div class="iw-body"> <div class="iw-body-tabs"> <ul class="clearfix"> <li><a href="#ftd-info">Info Warung</a></li> <li><a href="#ftd-tweets" class="last-of-type">Tweet Terbaru</a></li> </ul> </div> <div class="iw-body-wrap"> <div class="iw-body-main" id="ftd-info"> <div class="iw-box clearfix"> <div class="iw-grid2 iw-ftimg">'+fImgPath+'</div> <div class="iw-grid1"> <p><strong>E-Mail</strong></p> <p><a href="mailto:'+fEmail+'">'+fEmail+'</a></p> <br /> <p><strong>Buka Hari Ini Jam</strong></p> <p>'+fOpenToday+'</p> <br /> <p><strong>Nomor Telepon</strong></p> <p>'+fPhone+'</p> </div> </div> </div> <div class="iw-body-main" id="ftd-tweets"> <div class="iw-box clearfix"> <div class="iw-grid3"> <div class="tweets" title="'+fTwitter+'"></div> </div> </div> </div> </div> </div> </div> </div>';
boxText.innerHTML = boxContent;

  var ibOptions = {
     content: boxText
    ,disableAutoPan: false
    ,maxWidth: 0
    ,pixelOffset: new g.Size(25, -90)
    ,zIndex: 99
    ,closeBoxURL: "img/close.png"
    ,infoBoxClearance: new g.Size(1, 1)
    ,isHidden: false
    ,pane: "floatPane"
    ,enableEventPropagation: false
  };

  newMarkers[i].infobox = new InfoBox(ibOptions);

  g.event.addListener(marker, 'click', (function(marker, i) {
    return function() {
    for ( h = 0; h < newMarkers.length; h++ ) {
      newMarkers[h].infobox.close();
    }
    newMarkers[i].infobox.open(map, this);
    }
  })(marker, i));

  g.event.addListener(newMarkers[i].infobox, 'domready', function() {
    ibCallbacks();

    //Keep Centered
    $(".keep-centered").click(function(e){
    e.preventDefault();
    map.setCenter(clatlng[$(this).attr("data-index")]);
    });
  });

  /** End Infobox **/
  }
}
}


Deklarasikan variabel yang diperlukan. variabel newMarkers berupa array untuk menampung info marker, sedangakan variabel clatlng untuk menampung data latitute dan longitude setiap item.

var newMarkers = [],marker,clatlng = [];


Kemudian kita harus membuat markup untuk custom infowindow, seperti contoh di sini. Markup tersebut akan kita implementasikan pada fungsi infobox. Untuk referensi lengkap tentang infobos silakan baca di sini.

var boxText = document.createElement("div");
var boxContent = '<div class="iw-wrap"> <div class="iw-content"> <div class="iw-head clearfix"> <div class="ftd-org"> <a href="#" class="ftd-ftimg">'+fAvaPath+'</a> <div class="ftd-data vcard"> <p class="org">'+fName+'</p> <p class="adr"><span class="street-address">'+fAdr+'</span></p> <div class="ftd-tools"> <ul class="clearfix"> <li><a href="'+fWeb+'"><i class="i-web"></i>Visit Website</a></li><li><a href="#" class="keep-centered" data-index="'+i+'"><i class="i-centered"></i>Keep Centered</a></li> </ul> </div> </div> </div> </div> <div class="iw-body"> <div class="iw-body-tabs"> <ul class="clearfix"> <li><a href="#ftd-info">Info Warung</a></li> <li><a href="#ftd-tweets" class="last-of-type">Tweet Terbaru</a></li> </ul> </div> <div class="iw-body-wrap"> <div class="iw-body-main" id="ftd-info"> <div class="iw-box clearfix"> <div class="iw-grid2 iw-ftimg">'+fImgPath+'</div> <div class="iw-grid1"> <p><strong>E-Mail</strong></p> <p><a href="mailto:'+fEmail+'">'+fEmail+'</a></p> <br /> <p><strong>Buka Hari Ini Jam</strong></p> <p>'+fOpenToday+'</p> <br /> <p><strong>Nomor Telepon</strong></p> <p>'+fPhone+'</p> </div> </div> </div> <div class="iw-body-main" id="ftd-tweets"> <div class="iw-box clearfix"> <div class="iw-grid3"> <div class="tweets" title="'+fTwitter+'"></div> </div> </div> </div> </div> </div> </div> </div>';
boxText.innerHTML = boxContent;

var ibOptions = {
   content: boxText
  ,disableAutoPan: false
  ,maxWidth: 0
  ,pixelOffset: new g.Size(25, -90)
  ,zIndex: 99
  ,closeBoxURL: "img/close.png"
  ,infoBoxClearance: new g.Size(1, 1)
  ,isHidden: false
  ,pane: "floatPane"
  ,enableEventPropagation: false
};

newMarkers[i].infobox = new InfoBox(ibOptions);


Tambahkan event listener untuk membuka infobox (custom infoWindow) masing-masing saat marker di klik.

g.event.addListener(marker, 'click', (function(marker, i) {
  return function() {
    for ( h = 0; h < newMarkers.length; h++ ) {
      newMarkers[h].infobox.close();
    }
    newMarkers[i].infobox.open(map, this);
  }
})(marker, i));


Tambahkan satu event listener lagi, untuk fungsi-fungsi yang akan kita panggil saat infobox selesai dimuat. Dalam contoh ini kita akan memanggil fungsi ibCallbacks() yang telah kita buat sebelumnya, dan satu fungsi lagi untuk membuat center map saat icon center di klik.

g.event.addListener(newMarkers[i].infobox, 'domready', function() {
  ibCallbacks()
  $(".keep-centered").click(function(e){
    e.preventDefault();
    map.setCenter(clatlng[$(this).attr("data-index")]);
  });
 });


Setelah selesai menampilkan marker, kita perlu memanggil beberapa fungsi lain, yaitu untuk markerClusterer (berguna untuk menyederhanakan tampilan marker pada level zoom tertentu) dan juga fungsi untuk menampilkan marker saat meng-klik salah satu list item pada panel kiri yang kita buat sebelumnya. Baris berikut masih berada dalam callback getJSON, di luar loop marker.

var markerCluster = new MarkerClusterer(map, newMarkers);
$(".ft-name a").click(function(e){
  e.preventDefault();
  var index = $(".ft-name").index($(this).parent());
  g.event.trigger(newMarkers[index], 'click');
});


Callback untuk getJSON telah selesai. Kini saatnya menambahkan beberapa baris kode untuk pengaturan map options yang terletak pada panel, yaitu untuk menampilkan/menyembunyikan traffic layer pada map dan pengaturan antara map dan satellite view. Masih di dalam fungsi initialize() tambahkan baris berikut:

var trafficLayer = new g.TrafficLayer()
$("#map-view").click(function(){map.setMapTypeId(g.MapTypeId.ROADMAP);return false});
$("#sat-view").click(function(){map.setMapTypeId(g.MapTypeId.SATELLITE);return false});
var tog = false;
$("#toggle-traffic").click(function(){
  var icon = $("i",this),text = $("span",this);
  trafficLayer.setMap( !tog==true ? map : null );
  text.text( !tog==true ? "Hide Traffic" : "Show Traffic" );
  icon.toggleClass("i-showtr i-hidetr");
  tog = !tog;
  return false;
});


Panggil fungsi initialize() dan ibCallbacks()

initialize();
ibCallbacks();


Terakhir, tambahkan script untuk toggle dan custom scrollbar panel di sidebar.

$(".mp-toggle").click(function(e){
  e.preventDefault();
  var obj = $(this),el = $(this).parent();
  if(el.hasClass("visible")){
    el.animate({"left":"-380px"}).removeClass("visible");
    obj.find("i").toggleClass("arr-open arr-close");
  }else{
    el.animate({"left":"0"}).addClass("visible");;
    obj.find("i").toggleClass("arr-open arr-close");
  }
});
$("#foodmap-ft-list").jScrollPane(); 


Styles

Berikut styling css yang digunakan:

.map-content-wrap{
	position:relative;
	height:93%
}

.map-content-wrap #map_canvas{
	width:100%;
	height:100%
}

#map-panel{
	position:absolute;
	height:100%;
	top:0;
	left:0;
	z-index:99
}

#map-panel .mp-toggle{
	display:inline-block;
	background:#747047;
	padding:55px 3px;
	width:15px;
	text-align:center;
	position:absolute;
	right:-21px;
	top:21px;
	border-radius:0 5px 5px 0
}

#foodmap-ft-list{
	margin:10px 10px 10px 0;
	height:89%;
	overflow:auto;
	left:10px
}

#map-options{
	background:#f5f3e7;
	padding:5px 15px;
	margin-bottom:5px
}

#map-options p{
	float:left;
	margin-right:5px;
	font-size:11px;
	font-weight:bold;
	text-transform:uppercase;
	padding-top:5px
}

#map-options ul{
	float:left;
	display:inline-block
}

#map-options li{
	float:left;
	margin-left:1px;
	background:#b8b279;
	padding:1px 5px
}

#map-options li a,#map-options li span{
	color:#FFF;
	font-size:10px;
	text-transform:uppercase
}

#map-panel .mp-content, .iw-content{
	width:380px;
	z-index:99;
	height:95%;
	border-right:1px solid #747047;
	border-bottom:1px solid #747047;
	background:#FFF;
	padding:15px 0
}


Selesaiiiii! Download kode lengkapnya di sini dan mari makan peceeel! Hehe.

Heri Setiawan

Web designer dan front-end developer muda yang belum terlalu jelas dari spesies mana dia berasal. Pada sebuah eksperimen, dia mampu bertahan di dalam air selama 323,007645 detik, dan bisa melayang di udara dengan ketinggian mencapai 15,23 meter. Karena sering berpindah habitat, kini ia memutuskan untuk berada di darat dan menekuni dunia Web Design, HTML5, CSS, dan jQuery.

Follow me on Twitter

21 komentar di “Google Maps API, JSON, dan jQuery?”

  1. Vyatri says:

    Kereennn!!!

  2. Nanang says:

    Mantaps

  3. Eekhlas says:

    manteb bgd nih….q juga pengen buat webGIS buat skripsi q…..mohon pencerahanya…

  4. arul says:

    wah bagus tutornya gan, hehehe :D
    tutornya membantu sekali

  5. arul says:

    jika ingin menambahkan data baru bagaimana?
    semua data tersimpan pada pecel.json
    jika ingin dismpan ke dalam databse implemantasinya bagimana gan?

    • Benar, semua data tersimpan dalam pecel.json
      Untuk implementasi back-end semisal penggunaan database, Anda perlu meng-encode data terlebih dahulu ke dalam format JSON.

    • iksan hariji says:

      gun saya minta source codenya yah.. izin buat tugas akhir.. tapi saya ingin kembangkan lagi menggunakan json dynamic.. kalau yang di kode ini kan json static. maksudnya json dynamic file jsonnya dibuat sendiri. data datanya diload dari database

  6. Beben Koben says:

    Jadi kepengen bisa script euy…xixixi
    ajarin dong Om :p

  7. shitsuiima kasi says:

    mw tanya kalo data dan image yang diambil dari database gmn caranya nampilkan di info window..?

    masih baru belajar soalnnya

    terima kasih

  8. yandi says:

    gimana cara nampilin datanya dari mysql????
    maksudnya meng-encode data ke format json???

  9. afdi says:

    wezzz…
    manteb dah tutornya.
    menarik untuk dicoba + idenya kreatif banged.

  10. Teguh says:

    artikel yang sangat bagus,
    Oh iya bos, gmn caranya supaya markernya bisa beda-beda untuk setiap kategori, jadi misalnya ada 3 kategori
    warung pecel (marker1.jpg)
    warung tegal (marker2.jpg)
    warung soto (marker3.jpg)

    • Anda bisa menambahkan satu variable misal fType yang bisa berisi pecel, tegal, atau soto. Kemudian tambahkan conditional untuk membuat marker. Marker nya sendiri akan disimpan sebagai variable ‘marker’ seperti pada baris:

      marker = new g.Marker({map: map, position: latlng,icon: iconmark,shadow: shadowmark,clickable: true});

  11. accul says:

    Slm Mas ,,sangat menarik tulisannya,,
    ow iyya mw nax ne Mas ,,,
    klw pada marker atau markupnya digunakan file 3D format (.obj misalnya), bisa dibuat tdk itu mas ??mksh seblumnya Mas

  12. ilham says:

    gan, biar data yang ditampilin berasal dari database kan jeson nya harus di encode, nah, cara implementasi encode json nya nya bagaimana gan?
    ada tutorialnya? apakah perlu perubahan besar besaran dari tutor json static di atas (contoh: warung pecel)

    terimakasih gan

  13. Ipan Ginano says:

    salam gan, bagaimana cara mengganti kata info warung dan tweet terbaru di infowindow ??? thx gan

  14. ipanginano says:

    sudah gan, sudah terjawab, komentar saya sebelumnya, tidak di tampilkan dan dijawab juga gak apa2, saya sudah dapat jawabannya, terimakasih banyak

  15. lampz says:

    kalo mau di jadiin aplikasi android gmn ya om??
    kyk web apps gtu..

Tinggalkan Komentar

*