Random Thoughts on Random Things by Tanomsak
Random header image... Refresh for more!

แสดงหมุดจาก database ใน Google Maps ด้วย AJAX

21 Dec 2008

ความเดิมจากตอนที่แล้ว เราพูดถึงวิธีิการแสดงหมุดจาก database บนแผนที่ Google Maps ไปแล้ว แต่ติดตรงที่ว่าเวลามีหมุดเยอะๆจะแสดงหน้าเวปช้า และเปลือง memory คราวนี้ผมจะพูดถึงการใช้วิธีการแสดงหมุดจาก database เฉพาะส่วนที่มองเห็นในหน้าต่างแผนที่โดยการใช้ AJAX ครับ

ส่วน table database และ ข้อมูลใน database ก็ใช้ของคราวที่แล้วครับ (ดูได้ที่ Tutorial แบบบ้านๆ ตอนที่ 2 – แสดงหมุดจาก database ใน Google Maps)

สิ่งที่ต้องเตรียมก่อนเริ่ม

  1. ผมใช้ Prototype Javascript Framework สำหรับทำ AJAX เพราะมันติดมากับ Rails เลยชินครับ ถ้าใครถนัดตัวอื่นก็ตามสะดวก
  2. แนะนำ Firefox + Firebug สำหรับการ Debug ครับ สุดยอดมากๆ

หลักกาำรทำงาน

  1. ทุกครั้งที่มีกา่รเลื่อนแผนที่ หรือซูมเข้า/ซูมออก script จะขอข้อมูลจาก server และนำไปแสดงจุดพิกัดใหม่ในแผนที่
  2. ใช้พิกัดของแผนที่ ที่กำลังแสดงผล (x1,y1,x2,y2 ตรงมุมกรอบของแผนที่) เป็นตัวแปลในการเลือกข้อมูลพิกัดจาก database

อ้อ วิธีการที่จะเขียนถึง ส่วนใหญ่นำมาจากหนังสือ “Beginning Google Maps Applications with Rails and Ajax” นะครับ ลองไปหาอ่านดูกัน แนะนำๆ

ส่วนที่ 1 เรียกใช้ prototype.js โดยการเพิ่มบรรทัดต่อไปนี้ ในส่วน head

<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js" type="text/javascript"></script>

ส่วนที่ 2 แก้ไขส่วน Javascript โดยเพิ่ม function สำหรับแสดงหมุด และ แก้ไข function load() ดังนี้ครับ

var displayingMarkers = [];
var displayingMarkersNum = 0;
var deletingMarkers = [];
var deletingMarkersNum = 0;

function clearMarkers() {

for (var i = 0 ; i < deletingMarkersNum ; i++) {
map.removeOverlay(deletingMarkers[i]);
}

}

function updateMarkers() {
//เตรียม parameters พิกัดของแผนที่ที่กำลังแสดง เพื่อ query หมุดจาก database
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
var mapBoundary = 'ne=' + northEast.toUrlValue() + '&amp;amp;amp;sw=' + southWest.toUrlValue();
var myAjax = new Ajax.Request( '/get_marker', {
method: 'get',
parameters: mapBoundary,
onComplete: function(request){
// function นี้จะทำงานหลังจากได้รับค่า response จาก server
// ทำการเก็บค่า response จาก server เข้าตัวแปล markers
markers = eval( "(" + request.responseText + ")" );

// copy markers ที่กำลังแสดงอยู่เก็บไว้ เดี๋ยวเราจะลบหมุดพวกนี้ออก หลังจากเพิ่มหมุดชุดใหม่ในแผนที่แล้ว
deletingMarkers = displayingMarkers.clone();
deletingMarkersNum = displayingMarkersNum;
displayingMarkersNum = 0;
displayingMarkers.clear();

for (var i = 0 ; i < markers.length ; i++) {
var marker = markers[i]
var lat = marker.lat;
var lng = marker.lng;

//check for lat and lng so MSIE does not error on parseFloat of a null value
if (lat &amp;amp;amp;&amp;amp;amp; lng &amp;amp;amp;&amp;amp;amp; lat != 0 &amp;amp;amp;&amp;amp;amp; lng != 0) {
var latlng = new GLatLng(lat,lng)

var marker = new GMarker(latlng);

displayingMarkers[displayingMarkersNum] = marker;
displayingMarkersNum++;

map.addOverlay(marker);

} // end of if lat and lng
} // end of for loop

clearMarkers();

} // end of anonymous onComplete function

}); // end of the new Ajax.Request() call

}

function load() {
if (GBrowserIsCompatible()) {
displayingLandmarkNum = 0;
displayingLandmark.clear();
deletingLandmarkNum = 0;
deletingLandmark.clear();

var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);

updateMarkers();
GEvent.addListener(map,'zoomend',function() {
updateMarkers();
});

GEvent.addListener(map,'moveend',function() {
updateMarkers();
});
}
}

ส่วนที่ 3 เพิ่ม action ฝั่ง server ให้รับ AJAX request และ return ค่าพิกัด

def get_marker
ne = params[:ne].split(',').collect{|e|e.to_f}
sw = params[:sw].split(',').collect{|e|e.to_f}

# if the NE longitude is less than the SW longitude,
# it means we are split over the meridian.

if ne[1] > sw[1]
conditions = '((lng > ? AND lng < ?) AND (lat <= ? AND lat >= ?))'
else
conditions = '((lng >= ? OR lng < ?) AND (lat <= ? AND lat >= ?))'
end
markers = Marker.find :all, :select => 'id, lat, lng', :conditions => [conditions,sw[1],ne[1],ne[0],sw[0]]

render :text=>markers.collect{|c|c.attributes}.to_json
end

TIPS:

ลองสังเกตุหน้าต่าง console ของ Firebug เวลาเลื่อนแผนที่ดูครับ จะเห็นการสื่อสารระหว่าง browser กับ server เพิ่มขอข้อมูลพิกัดทุกครั้งที่มีการเลื่อนแผนที่

  • Smapa N
    อยากให้ลองเสนอราคาดูหน่อยครับ
    สวัสดีครับ
    อยากให้ลองเสนอราคาดูหน่อยครับ

    ตามรายละเอียดนี้ครับ
    http://www.thaiseoboard.com/index.php/topic,129386.msg1681226.html

    โดยหน้าค้นหาทางซ้ายขอปรับให้ look&feel คล้ายๆกับ
    http://www.allapartment.in.th/%E0%B8%AD%E0%B8%9E%E0%B8%B2%E0%B8%A3%E0%B9%8C%E0%B8%97%E0%B9%80%E0%B8%A1%E0%B9%89%E0%B8%99%E0%B8%97%E0%B9%8C-%E0%B8%AB%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%9E%E0%B8%B1%E0%B8%81-%E0%B8%AB%E0%B8%AD%E0%B8%9E%E0%B8%B1%E0%B8%81/%E0%B8%A7%E0%B8%B4%E0%B8%97%E0%B8%A2%E0%B8%B2%E0%B8%A5%E0%B8%B1%E0%B8%A2%E0%B8%99%E0%B8%AD%E0%B8%A3%E0%B9%8C%E0%B8%97%E0%B8%81%E0%B8%A3%E0%B8%B8%E0%B8%87%E0%B9%80%E0%B8%97%E0%B8%9E

    เวลากดแล้วอัพเดตได้ทันทีครับ แค่การนำเสนอให้ออกมาที่แผนที่แทนครับ

    ปัจจุบันผมใช้ระบบจูมล่าครับ ถ้าทำให้ไวกว่าก็จะดีมากครับ
    แต่ที่ผมต้องการมากที่สุดคือความเสถียรครับ เพราะ ช่วงเวลาที่คนค้นเยอะๆเว็บอืืดมากๆครับ

    ผมมี script ที่ใช้งานได้แล้วระดับนึงครับ คือคนเก่าเค้าเขียนไว้ครับ + เอา script มาโม คือ
    http://map.apartment.in.th/map.php

    ที่ยังขาดคือ เอาข้อมูลมาแสดงครับ ถ้าต้องการเข้าไปดู code ก็ยินดีนะครับ

    ขอให้เสนอราคามาครับ และขอชื่อ ติดต่อด้วยนะครับ

    ขอบคุณครับ

    นพ 083-757-1515
  • tanomsak
    สวัสดีครับคุณนพ ยินดีที่รู้จักครับ

    ขอบคุณที่สนใจอยากให้ผมทำงานนะครับ แต่ปกติผมไม่ได้รับงานพัฒนาเวปน่ะครับ

    เอาเป็นยินดีให้คำปรึกษาฟรีตามความสามารถของผมดีกว่าครับ
  • nuijang
    ขอบคุณมากครับที่เขียนบทความดีๆ มาให้อ่าน มีประโยชน์มากครับ
  • blossom
    อ่านแล้วมึนๆ ดีจังค่ะ มีแบบเป็น php มั้ยคะ
  • อุดมพงษ์ ค้าของ
    ขอบคุณครับท่าน(tanomsak) ขอให้เจริญในหน้าที่และการงานครับ
  • อุดมพงษ์ ค้าของ
    ถ้าไม่ยากเจอปัญหาการช้า หรือ กินแรม มีวิธีแนะนำมํยคับ ว่าจะใช้วิธีไหนในการพร๊อตจุดครั้งละเป็นพันจุด รบกวนพี่น้องที่รู้ช่วยตอบหน่อยนะคับ ไม่รู้จะทำยังไงปวดหมองมากเลย
  • tanomsak
    คงทำทำแบบ Ajax ครับ คือเอามาแสดงเฉพาำะส่วนที่เรามองเห็นในแผนที่ แล้วก็ เรียกจุึดใหม่ๆมาแสดงเวลาขยับแผนที่ครับ
  • อุดมพงษ์ ค้าของ
    เค้าว่ากันนะ...การปักหมุดบน Google เกิน "หนึ่งพันจุด" จะทำให้มีการแสดงผลออกมาหน้าเว็บช้ามากจิงรึป่าวคับท่านผู้ชม ช่วยตอบด้วยคับ เห็นเค้าว่าเกินพันจุด Google ทำให้ช้าเพื่อเก็บตังจิงป่าวครับพี่น้อง???
  • tanomsak
    ผมว่าจริงครับ ไม่ต้องถึงพันจุดหรอกครับ เป็นร้อยก็ช้าแล้วครับ browser จะกิน RAM อย่างดุเดือดเลย :) ไม่คงไม่ใช่เพราะ Google จะเก็บตังหรอกครับ
  • สุดยอด จิง ๆ คับ...
  • Khan
    คืออยากดูว่ามีไฟล์ไหนมั้งอ่าคะ

    เพราะไม่รู้จะเอาไปแปะตรงไหน

    ใครรู้ช่วยทีคะ ไม่ค่อยรู้เรื่องคอมคะ
  • kukuri
    คือว่า หาข้อมูลเกี่ยวกับพวกนี้แล้วมาเจออ่ะคะ แล้วอยากทราบเกี่ยวกับว่า ถ้า หาก เราดึงพิกัดจาก database มาแสดงบน แผนที่ และก็ทำเป็นpolygon อ่ะคะ แบบว่า พิกัด ของมุมที่ดินหนึ่งผืน และแต่ละผืนอาจจะมี สี่มุม ห้ามุม หรือ หกมุม อะไรพวกนั้นอ่ะคะ จะส่งค่ายังไงอ่ะคะ
  • lab
    รอหัวข้อต่อๆ ไปอยู่คับ
    ติดตามมาพอสมควรแล้ว จะอับเดทมะไหร่คับ T_T
  • ab
    ไม่มี ตัว อย่าง หรือ ครับ
  • tanomsak
    ยังไม่ได้ทำตัวอย่างเฉพาะสำหรับเรื่องนี้น่ะครับ ลองดูตัวอย่างที่ใช้งานจริงที่ http://www.ddproperty.com/ นะครับ สังเกตุพวก สถานที่ต่างๆในแผนที่

    ตอนนี้กำลังหาเวลาเขียนตอนต่อไปอยู่ครับ ยุ่งอยู่กับเรื่องอื่นเลย ดองเรื่อง google maps ยาวเลย
  • นัด
    ชอบมากคับ รอติดตามส่วนอื่นๆ อยู่คับ
blog comments powered by Disqus