วันเสาร์ที่ 20 เมษายน พ.ศ. 2556

Google Map API V.3 : ค้นหาแผนที่แบบ Autocomplete


    ผมเคยเขียนบทความสอนใช้งาน Google Map API มาบ้างแล้ว  ดูได้จาก Google Maps API
และบทความนี้ผมจะสอนเพิ่มช่องค้นหาเข้าไปด้วยครับ เพราะจะทำให้สามารถค้นหาตำแหน่งได้รวดเร็วยิ่งขึ้น โดยที่ไม่จำเป็นต้องหาตำแหน่งในแผนที่เองโดยการเลื่อนแผนที่ไปยังตำแหน่งที่เราต้องการ
    เนื่องจากการทำงานของมัน คือ จะเลื่อนหมุดไปยังตำแหน่งที่เราค้นหาให้เราโดยอัตโนมัติ และการค้นหาจะทำงานแบบ Autocomplete
มาดูโค๊ดกันเลยดีกว่า

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=windows-874" />
        <title>สอนค้นหาแบบ autocomplete ใน google map api v3</title>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places&language=th"></script> 
        <script>
            function initialize() {
                var geocoder;
                var infowindow;
                var place;
                var marker;
                geocoder = new google.maps.Geocoder();
                var Position = new google.maps.LatLng(13.723419, 100.476232);
                var mapOptions = {
                    center: Position, //ตำแหน่งแสดงแผนที่เริ่มต้น
                    zoom: 13, //ซูมเริ่มต้น คือ 8
                    mapTypeId: google.maps.MapTypeId.ROADMAP //ชนิดของแผนที่
                };
                var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
                var input = document.getElementById('searchTextField');
                infowindow = new google.maps.InfoWindow();
                marker = new google.maps.Marker({
                    position: Position,
                    draggable: true
                });
                marker.setMap(map);//แสดงตัวปักหมุด!!
                showMapVal(Position.jb, Position.kb);
                var autocomplete = new google.maps.places.Autocomplete(input);
                autocomplete.bindTo('bounds', map);
                google.maps.event.addListener(autocomplete, 'place_changed', function() {//ทำงานเมื่อคลิกที่รายการค้นหา

                    infowindow.close();
                    marker.setVisible(false);
                    input.className = '';
                    place = autocomplete.getPlace();
                    showMapVal(place.geometry.location.jb, place.geometry.location.kb);
                    if (!place.geometry) {
                        input.className = 'notfound';
                        return;
                    }
                    if (place.geometry.viewport) {
                        map.fitBounds(place.geometry.viewport);
                    } else {
                        map.setCenter(place.geometry.location);//Set Center ของแผนที่ตามตำแหน่งที่ค้นหา
                        map.setZoom(17);//กำหนดซูมแผนที่ขยายเป็น 17
                    }
                    marker.setPosition(place.geometry.location);//setตำแหน่งใหม่ที่ค้นหา
                    marker.setVisible(true);//แสดงหมุดในตำแหน่งใหม่ที่ค้นหา
                    var address = '';
                    if (place.address_components) {
                        address = [
                            (place.address_components[0] && place.address_components[0].short_name || ''),
                            (place.address_components[1] && place.address_components[1].short_name || ''),
                            (place.address_components[3] && place.address_components[3].short_name || ''),
                            (place.address_components[2] && place.address_components[2].short_name || '')
                        ].join(' ');
                    }
                    infowindow.setContent('<div><strong>' + place.name + '</strong>' + address);
                    infowindow.open(map, marker);
                });

                google.maps.event.addListener(marker, 'dragend', function(ev) {//ทำงานเมื่อคลิกเคลื่อนย้ายหมุด (Marker)
                    var location = ev.latLng;
                    var lat = location.lat();
                    var lng = location.lng();
                    showMapVal(lat, lng);
                    var latlng = new google.maps.LatLng(lat, lng)
                    geocoder.geocode({'latLng': latlng}, function(results, status) {


                        if (status == "OK") {
                            var address = '';
                            if (results[0].address_components) {
                                var address = [
                                    (results[0].address_components[0] && results[0].address_components[0].short_name || ''),
                                    (results[0].address_components[1] && results[0].address_components[1].short_name || ''),
                                    (results[0].address_components[2] && results[0].address_components[2].short_name || ''),
                                    (results[0].address_components[3] && results[0].address_components[3].short_name || ''),
                                    (results[0].address_components[5] && results[0].address_components[5].short_name || ''),
                                    (results[0].address_components[4] && results[0].address_components[4].short_name || '')
                                ].join(' ');
                                infowindow.setContent(address);
                                infowindow.open(map, marker);
                            }
                        }
                    });
                });

                google.maps.event.addListener(map, 'zoom_changed', function(ev) {//ซูมแผนที่
                    zoomLevel = map.getZoom();//เรียกเมธอด getZoom จะได้ค่าZoomที่เป็นตัวเลข
                    $('#mapsZoom').val(zoomLevel);//เอาค่า Zoom Level ไปแสดงที่ textfield ที่มี id="mapsZoom"
                });
            }
            
            function showMapVal(lat, lng) {//ฟังก์ชั่นแสดงละติจูดกับลองติจูดใน textfield
                $("#mapsLat").val(lat);//textfield ที่ค่า id="mapsLat"
                $("#mapsLng").val(lng);//textfield ที่ค่า id="mapsLng"
            }
            google.maps.event.addDomListener(window, 'load', initialize);//ทำงานตอนหน้านี้โหลดเสร็จแล้วให้ไปเรียกฟังก์ชั่น initialize
        </script>
        <style>
            body {
                font-family: sans-serif;
                font-size: 14px;
            }
            #map-canvas {
                height: 400px;
                width: 600px;
                margin-top: 0.6em;
            }
            input {
                border: 1px solid  rgba(0, 0, 0, 0.5);
            }
            input.notfound {
                border: 2px solid  rgba(255, 0, 0, 0.4);
            }
        </style>
    </head>

    <body>

        ค้นหาสถานที่ <input id="searchTextField" type="text" size="50"> 
        Ex. ร้านอาหาร,โรงพยาบาล,10200
            <div id="map-canvas"></div>
            <div>

                ละติจูด: <input type="text" size="20" id="mapsLat" />  


                ลองติจูด <input type="text" size="20" id="mapsLng" />  


                ซูม <input type="text" size="3" id="mapsZoom" value="8" />  

            </div>
    </body>
</html>

ศึกษาเพิ่มเติมได้จาก https://developers.google.com/maps/documentation/javascript/places#places_autocomplete

สามารถศึกษาวิธีบันทึกลงฐานข้อมูลได้จาก บทความ ลองเล่นกับ Google Map API V.3 : ประยุกต์ใช้ร่วมกับ PHP และฐานข้อมูล MySQL

15 ความคิดเห็น :

  1. Copy..โค้ด...ไปวางที่..Appserv....แล้ว Run
    แล้ว Map ไม่ขึ้นครับ....
    Autocomplete....ก็ไม่ขึ้นครับ..
    ไม่ทราบว่า...ต้องแก้ตรงส่วนไหนครับ...
    แต่ตัวอย่างที่ใช้ กับ SQL Map ขึ้นครับ...

    ตอบลบ
    คำตอบ
    1. แก้ไขให้แล้วครับ ^^ ขอบคุณที่แจ้งปัญหานะครับ

      ลบ
  2. หลังจากกดเลือก ข้อความจาก Autocomplete แ้ล้วว...
    ทำไมตัวเลขใน textfidld ของ ละติจูด ไม่ขึ้นครับ...
    ขึ้นเฉพาะตัว textfidld ของ ลองติจูด อย่างเดียวครับ...

    มันจะขึ้นตัวเลขทั้งสอง 2 ช่อง เฉพาะตอนไปเลื่อน หมุด ครับ...

    ตอบลบ
    คำตอบ
    1. ของผมโชว์นะครับ เพราะได้ลองเทสดูแล้ว

      ลบ
    2. ขอบคุณครับ..........
      ตอนนี้ขึ้นครบทั้งสอง ช่องแล้วครับ....
      จะได้เก็บที่ SQL ได้สักที............

      ลบ
  3. ขอบคุณมากๆ นะครับ ที่แบ่งปันกัน :)

    ตอบลบ
  4. คุณคะ ขอบคุณมากค่ะ เพอร์เฟคมาก ๆ

    แล้วรบกวนช่วยทำบทความสอนเรื่อง แนะนำเส้นทางกับบอกระยะทาง + เวลาที่ใช้ ด้วยได้มั้ยคะ >.<

    ตอบลบ
    คำตอบ
    1. เดี๋ยวว่างๆจะเขียนให้อ่านนะครับ ลองไปศึกษาเรื่องของ polyline ดูครับ

      ลองดูเว็บนี้ครับ http://www.ninenik.com/%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%87%E0%B8%B2%E0%B8%99_polyline_%E0%B9%81%E0%B8%A5%E0%B8%B0_polygon_%E0%B9%83%E0%B8%99_google_map_api_v3-380.html

      ลบ
  5. ขอบคุณค้ะะ ^^

    ตอบลบ
  6. ไม่ระบุชื่อ1 สิงหาคม 2556 เวลา 11:27

    ถ้าต้องการให้แสดงข้อมูลสถานที่ใน Text area เช่น ถนน ราชพฤกษ์ แขวง บางจาก เขต ภาษีเจริญ กรุงเทพมหานคร TH กรุงเทพมหานคร ต้องทำอน่างไรครับ

    ตอบลบ
    คำตอบ
    1. บรรทัดที่ 60 จะเห็นคำสั่ง
      infowindow.setContent('<div><strong>' + place.name + '</strong>' + address);
      บรรทัดต่อมา ให้ใส่โค๊ Text area ของทั่นได้เลยครับ เช่น
      $('#textgoo').html('<div><strong>' + place.name + '</strong>' + address);

      จากโค๊ดด้านบน เราจะต้องสร้างtextareaตามนี้นะ
      <textarea id="textgoo"></textarea>

      ลบ
  7. กดเลือก จาก Autocomplete แล้ว ค่า ละติจูด และ ลองติจูด ไม่ขึ้นครับ แต่ตอนย้ายหมุดถึงขึ้นนะครับ ไม่รู้เป็นเพราะอะไร

    ตอบลบ
    คำตอบ
    1. google เปลี่ยนคำสั่งใหม่ คำสั่งเดิมใช้ไม่ได้แล้วครับ

      ลบ