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

เพิ่มหมุดจาก Google Maps ลง Database

24 Dec 2008

ในเวป ddproperty.com ที่ผมกับเพื่อนดูแลอยู่เนี้ย เราให้คนที่ลงประกาศทุกคนต้องระบุตำแหน่งด้วยว่า อสังหาฯที่กำลังลงประกาศตำแหน่งอยู่ตรงไหน ผมก็ใ้ช้ google maps นี้แหละครับในการระบุตำแหน่ง

คราวนี้เราจะมาดูกันว่า จะใช้ Google Maps เพิ่มตำแหน่งหมุดใน Database ยังไง จริงๆแล้ว trick หลักๆก็คือว่าเราจะเอาค่าตำแหน่ง lat, lng ของจุดที่เราต้องการออกมาจาก Google Maps ได้ยังไง ส่วนการบันทึกค่าลง database ก็ทำเหมือนกับการส่งค่าจาก form ตามปกติ ขั้นตอนคร่าวๆเป็นแบบนี้ครับ

  1. หาค่า lat, lng จากตำแหน่งที่ click บนแผนที่
  2. เขียนค่า lat, lng ไว้ใน hidden fields ของ form ที่เราจะใช้ส่งค่ากลับไปฝั่ง server
  3. ทางฝั่ง server ก็รับกา่ร submit แล้วก็เขียนค่าลง database

ง่ายไหมครับ ลองมาดูกันทีละขั้น

ขั้นแรก หาค่า lat, lng จากตำแหน่งที่ click บนแผนที่

Google Maps API มี function ต่างๆที่เตรียมไว้ให้ใช้งานเยอะมากครับ รวมถึงเมื่อผู้ใช้ Interactive กับแผนที่เช่น Click บนแผนที่ ซูมเข้า ซูมออก หรือว่าจะขยับหมุดก็มี Event เกี่ยวข้องทั้งหมด สิ่งที่เราต้องทำเพื่อหาตำแหน่งที่ผู้ใช้งาน Click บนแผนที่ก็คือสร้าง Listerner เพื่อมาดักจับ Event เหล่านี้ ซึ่งทำได้อย่างนี้ครับ

 GEvent.addListener(map, "click", function(overlay, latlng) { /*เรา check ค่า overlay เพื่อดูว่าเป็นการกดบนแผนที่ หรือว่ากดบน overlay ที่อยู่บนแผนที่เช่น marker โดยตัวแปล overlay จะมีค่าเป็น null ในกรณีที่กดบนแผนที่เปล่าๆ*/ if (!overlay) { var lat = latlng.lat(); var lng = latlng.lng(); } }); 

โดย Event “click” เนี้ยจะส่งค่าตัวแปลไปให้ function ที่เราเขียนขึ้นมารับด้วย คือ overlay และ latlng โดย overlay จะเป็นตัวบอกว่าเป็นการ click บนแผนที่ หรือว่า click บน overlay ส่วน latlng จะเป็นตัวแปลประเภท GLatLng ซึ่งมี method lat(), lng() เพื่อหาค่า lat, lng แค่นี้เราก็จะได้ค่า lat, lng ของตำแหน่งที่ click บนแผนที่แล้วครับ

เขียนค่า lat, lng ไว้ใน hidden fields ของ form ที่เราจะใช้ส่งค่ากลับไปฝั่ง server

อันนี้ก็ตรงไปตรงมาครับ โดยเราจะำสร้าง form ที่มี hidden fields ชื่อ lat กับ lng ไว้ แล้วทำการ update ค่าทุกครั้งที่มีกาีร click บนแผนที่

</p> <form action=&quot;/new_marker&quot;> <p><input name=&quot;marker[name]&quot; size=&quot;30&quot;/> <input name=&quot;marker[address]&quot; size=&quot;30&quot;/> <input type=&quot;hidden&quot; id=&quot;marker_lat&quot; name=&quot;marker[lat]&quot;/> <input type=&quot;hidden&quot; id=&quot;marker_lng&quot; name=&quot;marker[lng]&quot;/> <input type=&quot;submit&quot; name=&quot;commit&quot; value=&quot;submit&quot;/></p> </form> <p>

แล้วก็จัดกา่รแก้ไข javascript ของเราให้ Update value ของ hidden fields lat, lng สังเกตุว่า ผมใช้ $(‘marker_lat’) แทนการ getElementById เพราะผมใช้ Prototype Framework อันนี้เพราะผมชินครับ ส่วนใครจะใช้ javascript แบบมาตราฐานก็ตามสะดวกครับ

 var map; var present = null; function updateHiddenFields(marker) { latlng = marker.getLatLng(); var lng = latlng.lng(); var lat = latlng.lat(); $('marker_lat').value = lat; $('marker_lng').value = lng; } function addMarker(latlng) { if (!present) { /*ใส่ options draggable เป็น true เพื่อให้สามารถย้ายตำแหน่งของหมุดได้ ส่วน bouncy เป็น false เพื่อไม่ให้หมุดเด้งหลังการย้ายตำแหน่ง*/ var newMarker = new GMarker(latlng, { draggable: true, bouncy: false}); map.addOverlay(newMarker); /*ตรวจจับ Event dragend เพื่อทำการ update ค่า lat,lng เมื่อมีย้ายหมุด*/ GEvent.addListener(newMarker, &quot;dragend&quot;, function() { updateHiddenFields(newMarker); }); updateHiddenFields(newMarker); map.panTo(latlng); present = true; } } function load() { if (GBrowserIsCompatible()) { map = new GMap2(document.getElementById(&quot;map&quot;)); map.setCenter(new GLatLng(37.4419, -122.1419), 13); GEvent.addListener(map, &quot;click&quot;, function(overlay, latlng) { if (!overlay) { addMarker(latlng); } }); } } 

เนื่องจากผมต้องการให้ระบุตำแหน่งทีละหนึ่งอัน (หนึ่งอสังหาฯ หนึ่งตำแหน่ง) เลยต้องมีตั้งค่าตัวแปล present เอาไว้ check ไม่ให้เพิ่มหมุดซ้ำ

ทางฝั่ง server รับกา่ร submit แล้วก็เขียนค่าลง database

ที่นี้ก็จัดกา่ร insert ค่าที่ได้รับจาก form ลง database ครับ

 def new_marker _marker = params[:marker] @marker = Marker.new(_marker) @marker.save! end 

เท่านี้ก็เป็นอันเรียบร้อยครับ ลองดูตัวอย่าง ลองดู Firebug console นะครับว่า ค่า value ของ hiddle fields เปลี่ยนหลังจากย้ายหมุดตามที่ต้องการหรือเปล่า

Del.icio.us : ,
Technorati : ,

  • มือใหม่

    อยากให้เขียนเอาค่า ละติจูดและลองติจูด จากฐานข้อมูลขึ้นมาโชว์บน Google maps ครับ ขอความกรุณาด้วยครับ

  • tanomsak

    ลองดูที่ http://www.tanomsak.com/index.php/2008/12/googl… นะครับ ถ้าสงสัยตรงไหนก็ถามได้เลยนะครับ ผมมือใหม่หัดเขียน blog เหมือนกันครับ

  • มือใหม่

    ขอบคุณครับแต่ว่ามีเป็นแบบ PHP ไหมครับ

  • tanomsak

    ผมใช้เป็นแต่ RoR อะครับ
    ลองทำความเข้าใจแล้วเปลี่ยนเป็น PHP ดูนะครับ :) ทำได้แล้วอย่าลืม มาเล่าให้ฟังด้วยครับว่าทำไง

  • มือใหม่

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

  • มือใหม่

    แล้วที่ผมทำการดึงค่าจากละติจูดและลองติจูดจากฐานข้อมูลขึ้นมาโชว์บนแผนที่นั้นก็ไม่มีอะไรเลยครับ 55+ ทำแบบง่ายๆเลย เขียนเปิดฐานข้อมูลแล้วก็ echo ค่าต่างๆออกมาเอาครับ จากค่ามาร์กเกอร์ที่มันจะระบุไว้ตายตัวผมก็เอาคำสั่ง<?php echo $row1 ["lat"] ?>ไปแทนที่ซะมันก็จะดึงเอาพิกัดที่มีอยู่ในฐานข้อมูลดึงออกมาให้เราเองครับแค่นี้ครับ

  • chokul

    จากรูปข้างบน icon 3 อันที่อยู่ข้างๆ แผนที่เอามาจากไหนค่ะ

    แล้วต้องทำยังไงถึงจะมีiconแบบนี้ค่ะ

  • tanomsak

    เอามาปุ่มขาวๆมาจาก maps.google.com ครับ แล้วมาวาดรูปข้างในเอง ส่วนวิธีเิอารูปมาใช้เป็นการทำ custom control ครับ

    อยากเขียนถึงเรื่องนี้เหมือนกันครับ แ่่ต่ว่ายุ่งมากๆขอแบบย่อก่อนนะครับ จริงๆแล้ว icon ที่เห็นมันคือ DIV 3 อันที่มี background เป็นรูปภาพ icon +, – , หมุด

    ผมสร้าง DIV ขึ้นมาตั้งค่า CSS ต่างๆให้สวยงาม แล้วก็ bind event onclick ให้กับ DIV แต่ละอันให้ตรงกับ icon เช่น ปุ่ม + ก็มี code ประมาณนี้

    GEvent.addDomListener(zoomInDiv, “click”, function() {
    map.zoomIn();
    });

    แล้วก็ add ปุ่มพวกนี้ลงไปใน map โดย

    map.getContainer().appendChild(zoomInDIV);

    ประมาณนี้ครับ งงไหมเอ่ย ลองเล่นดูนะครับ clear งานได้เมื่่อไหร่จะมาเขียนต่อครับ

  • blythe

    ถ้าต้องการให้เปลี่ยนแบบของหมุดอ่ะค่ะ

    จะต้องสร้า้งฟังก์ชั่นยังไงค่ะ
    ให้เลือกหมุดได้หลายๆแบบค่ะ

  • Pingback: Tutorial แบบบ้านๆ ตอนที่ 1 - Basic Google Maps API — tanomsak.com

  • indysoft

    ต้องขอขอบคุณพี่มากเลยครับ ผมกำลังทำโปรเจคเกี่ยวกับ Google Maps API อยู่ด้วยครับ

    ของพี่ออกแบบได้สวยดีครับ อั๊พข้อมูลเรื่อยๆนะครับ กำลังติดตามอย่างตั้งใจ

  • tanomsak

    ิยินดีึีืที่มีประโยชน์ และได้คนติดตามอ่านเพิ่มอีกหนึ่งครับ :)

  • http://twitter.com/kobdesign kobdesign

    Test Twitter Connect

  • pasinty

    ช่วยแนะนำ การค้นหาหมุดที่เราสร้างขึ่นเองครับบน google map โดยค้นจาก texbox หรืืิอ listbox ก็ได้ครับ หามา เป็นอาทิตย์แล้วครับ

  • poe ค่ะ

    -/- ก่อนอื่นต้องขอขอบคุณ tanomsak ที่เขียนบทความนี้มีประโยชน์มากเลยค่ะ แต่อยากให้เพิ่มเติมส่วนนึงค่ะ คืออยากให้มันแสดงหมุดก่อนเลื่อนไปตำแหน่งอื่นค่ะ ทำ code ต่อจากคุณ tanomsak มาหลายวันแล้วยังไม่ได้เลย ขอความกรุณาด้วยค่ะ ^-^

  • lovetummy

    def new_marker _marker = params[:marker] @marker = Marker.new(_marker) @marker.save! end
    ช่วยอธิบายโค้ดนี้หน่อยครับ เผื่อผมจะไปปรับใช้กับ php

  • tanomsak

    params[:marker] เป็น parameter ที่รับมาจาก browser ครับ

    โดย Marker.new(_marker) @marker.save! ก็คือสร้าง record ใน database ด้วย parameter ที่รับมาจาก browser ครับ

  • Man_guitarsolo

    คือผมมีปัญหาขอคำปรึกษาหน่อยครับ คือ ผมทำเว็บไซต์เกี่ยวกับการลงประกาศงาน ทีนี้ ก็อยากนำเอา Google Map API ไปใช้กับบริษัทรับสมัครงานให้สามารถระบุตำแหน่งที่ตั้งของบริษัทได้ กระบวนการทำงานคือ หลังจากบริษัทได้ทำการสมัครสมาชิกกับเว็บผมแล้ว ก็จะสามารถล็อกอินเข้าสู่ระบบเพื่อ แก้ไข ตำแหน่งแผนที่ Google map แทนที่จะเป็น การ Insert ข้อมูลใหม่ ดังนั้นผมจำเป็นต้องใช้ คำสั่ง sql update ที่ตาราง tbl_company ในฟิลด์ lat,lng ที่ผมออกแบบไว้ โดยผมใช้หลักการ คลิกบนแผนที่ แล้วมี pop up ขึ้นมาให้ confirm lat,lng พอคลิก ปุ่ม บันทึกใน pop up ก็จะส่ง url และ parameter ไปให้ไฟล์php ทำกระบวนการ update lat,lng เข้าตาราง tbl_company ซึ่งไม่ทราบว่า sql update ของผมผิดตรงไหนหรือเปล่า ช่วยดูให้ผมหน่อยครับ

    ตัวอย่าง sql update ของผม
    $updateSQL = sprintf(“UPDATE tbl_company SET lat=%s,lng=$s WHERE company_id=$s”,
    GetSQLValueString($latitude),
    GetSQLValueString($longtitude),
    GetSQLValueString($company_id));

    ุถ้าใช้ sql insert ด้านล่างก็ผ่านครับ
    $query = sprintf(“INSERT INTO markers ” .
    ” (lat, lng ) ” .
    ” VALUES ('%s', '%s' );”,
    mysql_real_escape_string($lat),
    mysql_real_escape_string($lng));

  • tanomsak

    ผมเขียน php ไม่เป็นนะครับ แต่เท่าที่ดูเหมือนกับว่าตอน insert จะมีเครื่องหมายคำพูด ” ' ” อยู่ตรง value แต่ว่าตอน update ไม่มีหรือเปล่าครับ

  • Ba_nana55

    สวัสดีค่ะ

    คืออยากจะถามว่า

    อยากได้แบบว่า พิมชื่อสถานที่ลงไปใน input box ที่เราสร้าง

    จากนั้นหมุดก้อจะไปปักบนแผนที่ในตำแหน่งนั้นเองอะค่ะ

    พอจะมีวิธีมั้ยค่ะ

    ขอบคุณค่ะ

  • tanomsak

    ก็พอทำได้ครับ แต่ว่าไม่ 100% ว่าจะสามารถเจอสถานที่ ที่ระบุหรือเปล่าครับ วิธีนี้เรียกว่า Geocoding ครับ

    ลองดู http://code.google.com/apis/maps/documentation/geocoding/#Geocoding ครับ

  • Ba_nana55

    ขอบคุณค่ะ

    จากตัวอย่างด้านบนอะค่ะ

    เหนว่ามีการให้ระบุจังหวัด และ เขตไปก่อน

    จากนั้นบนแผนที่จะขยับให้เองอัตโนมัติ

    ส่วนตรงนี้คือ ใช้เซอร์วิส หาละติจุด ลองติจูด หรือว่าพี่เก็บตำแหน่งแต่ละจังหวัดไว้ในดาต้าเบสคร่ะ

    แร้วถ้าใช้เซอร์วิส ทำอย่างไรค่ะ เหมือนกับวิธีที่พี่บอกมาข้างต้นหรือป่าว

    ขอบคุณค่ะ

  • Piglet

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

  • tanomsak

    ถ้าที่ว่าติดตามได้แล้วหมายถึงแสดงรถยนต์บนแผนที่จากพิกัดที่ส่งมาทาง GPRS ได้แล้วล่ะก็ไม่น่าจะยากแล้วนะครับ คือน่าจะทำเหมือนกับรถคันที่หนึ่งแหละครับ แต่ว่ากำหนดหมุด (รถ?) เพิ่มอีกคันนึง

  • Piglet

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

    นี้คือโปรแกรมที่เขียนอยู่ค่ะ ช่วยดูให้หน่อยนะค่ะ

    var iconBlue = new GIcon();
    iconBlue.image =

    http://labs.google.com/ridefinder/images/mm_20_blue.png';
    iconBlue.iconSize = new GSize(12, 20);
    iconBlue.shadowSize = new GSize(22, 20);
    iconBlue.iconAnchor = new GPoint(6, 20);
    iconBlue.infoWindowAnchor = new GPoint(5, 1);

    var customIcons = [1];
    customIcons["1"] = iconBlue;

    var iconRed = new GIcon1();
    iconRed.image =

    http://labs.google.com/ridefinder/images/mm_10_Red.png';
    iconRed.iconSize = new GSize(12, 10);
    iconRed.shadowSize = new GSize(22, 10);
    iconRed.iconAnchor = new GPoint(6, 10);
    iconRed.infoWindowAnchor = new GPoint(5, 1);

    var customIcons = [2];
    customIcons["2"] = iconRed;

    function load() {
    if (GBrowserIsCompatible()) {
    var map = new GMap2(document.getElementById(“map”));
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    map.setCenter(new GLatLng(13.7225 , 100.76328), 15);

    GDownloadUrl(“xmlallv1.php”, function(data) {
    var xml = GXml.parse(data);
    var markers =

    xml.documentElement.getElementsByTagName(“marker”);
    for (var i = 0; i < markers.length; i++) {
    var Dat = markers[i].getAttribute("Dat");
    var Time = markers[i].getAttribute("Time");
    var Spd = markers[i].getAttribute("Spd");

    var point = new GLatLng(parseFloat(markers

    [i].getAttribute("lat")),
    parseFloat(markers[i].getAttribute

    ("lng")));

    var marker2 = createMarker(point, Dat, Time,Spd);
    map.addOverlay(marker2);
    }
    });

    GDownloadUrl("xmlallv1new.php", function(data) {
    var xml = GXml.parse(data);
    var markers =

    xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
    var Dat = markers[i].getAttribute("Dat");
    var Time = markers[i].getAttribute("Time");
    var Spd = markers[i].getAttribute("Spd");

    var point = new GLatLng(parseFloat(markers

    [i].getAttribute("lat")),
    parseFloat(markers[i].getAttribute

    ("lng")));

    var marker3 = createMarker(point, Dat, Time,Spd);
    map.addOverlay(marker3);
    }
    });
    }
    }

    function createMarker(point, Dat, Time,Spd) {
    var marker2 = new GMarker(point, {icon:iconBlue});
    var html = " Date “+Dat+”“+”Time “+”

    +Time+”“+”point

    “+”“+point+”“+”Spd”+”“+Spd+”“;
    GEvent.addListener(marker2, ‘click’, function() {
    marker2.openInfoWindowHtml(html);
    });

    return marker2;
    }

    function createMarker(point, Dat, Time,Spd) {
    var marker3 = new GMarker(point, {icon:iconRed});
    var html = “ Date “+Dat+”“+”Time “+”

    +Time+”“+”point

    “+”“+point+”“+”Spd”+”“+Spd+”“;
    GEvent.addListener(marker3, ‘click’, function() {
    marker3.openInfoWindowHtml(html);
    });

    return marker3;
    }

  • Pebble Ploy

    ถ้าจะให้ค่า lat lng มาแสดงในช่องเดียวกันแล้วคั่นด้วยเครื่องหมาย , จะทำยังไงอ่ะค่ะ รบกวนตอบด้วยนะค่ะ