การค้นหาสถานที่ด้วย Places search box และแสดงผลภาพจากข้อมูล Street View บน Google Maps

       ความเดิมจากตอนที่แล้วของบทความ “การดึงค่าละติจูดและลองจิจูดของสถานที่ด้วย Places search box บน Google Maps” เพื่อแก้ปัญหาในการดึงค่าละติจูด-ลองจิจูดจากชื่อสถานที่ที่ผู้ใช้พิมพ์ค้นหาไว้ โดยมีการนำ “Places search box” มาใส่ไว้ในแผนที่ที่เราต้องการแทนนั้น ถือเป็นตัวช่วยให้กับผู้ใช้ในระดับหนึ่ง  แต่สำหรับในบทความนี้ ผู้เขียนจะขอต่อยอดความรู้ดังกล่าว โดยได้ศึกษาและนำวิธีการแสดงผลภาพจากข้อมูล Street view มาประยุกต์ใช้ร่วมด้วย เพื่อให้ผู้ใช้สามารถมองเห็นสถานที่จริงที่เลือกได้จากแผนที่ได้ด้วย ซึ่งจะยิ่งช่วยอำนวยความสะดวกให้กับผู้ใช้ ทำให้ผู้ใช้สามารถตรวจสอบได้ว่าสถานที่ดังกล่าวเป็นสถานที่ที่ต้องการจะดึงค่าละติจูด-ลองจิจูดจริงหรือไม่ได้อีกทางหนึ่งนั่นเอง ซึ่งวิธีการบางส่วนจะขอยกยอดมาจากบทความก่อนหน้านี้ เกี่ยวกับเรื่องการดึงค่าละติจูด-ลองจิจูดจากการค้นหาโดยใช้ Places search box และจะขอเพิ่มเติมความสามารถในการแสดงผลภาพ Street View  รวมทั้งสามารถคลิกจุดพิกัดใหม่บนแผนที่ เพื่อค้นหาตำแหน่ง สถานที่ตั้ง และรายละเอียด รวมถึงภาพจาก Street View ได้อีกด้วย เพื่อให้การดึงค่าพิกัดใกล้เคียงความจริงมากที่สุด โดยมีวิธีการดังนี้

  • ส่วนของสไตล์ชีทในการแสดงผล ขึ้นกับการตกแต่งของผู้พัฒนาแต่ละท่าน
<!—ส่วนของ Style Sheets->
<style>
html, body {
 height: 100%;
 margin: 0;
 padding: 0;
}
#map {
 width: 100%;
 height: 400px;
}
.controls {
 margin-top: 10px;
 border: 1px solid transparent;
 border-radius: 2px 0 0 2px;
 box-sizing: border-box;
 -moz-box-sizing: border-box;
 height: 32px;
 outline: none;
 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
#searchInput {
 background-color: #fff;
 font-family: Roboto;
 font-size: 15px;
 font-weight: 300;
 margin-left: 12px;
 padding: 0 11px 0 13px;
 text-overflow: ellipsis;
 width: 80%;
}
#searchInput:focus {
 border-color: #4d90fe;
}

</style>
  • ส่วนของการอ้างอิง libraries เพื่อใช้งาน Google API
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCRbMoDPc_mTv3D3QPqe0Ar84nSvRhA8nk&libraries=places&callback=initMap" async defer></script>
  • ส่วนของการประกาศค่าเริ่มต้นและตัวแปร รวมถึงการเรียกใช้งานฟังก์ชั่นเพื่อใช้ในการแสดงผล
    • ฟังก์ชั่น initMap() ซึ่งจะเรียกใช้งานตอนเริ่มต้นโหลดหน้าจอขึ้นมา
<script>
 var panorama;
 var map;
 var markers = [];
/***** function ในการประกาศค่าเริ่มต้นให้กับแผนที่*****/
 function initMap() {

/***** ประกาศตำแหน่งพิกัดกึ่งกลางให้กับการแสดงผลแผนที่ ในที่นี้กำหนดเป็นกรุงเทพมหานคร*****/
 var center_point = { lat: 13.7563309, lng: 100.50176510000006 };
 var sv = new google.maps.StreetViewService();

/***** เป็นส่วนของการแสดงผลภาพจาก Street View *****/
 panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'));

 /***** กำหนดรายละเอียดคุณสมบัติของแผนที่*****/
 var map = new google.maps.Map(document.getElementById('map'), {
 center: {lat: center_point.lat, lng: center_point.lng},
 zoom: 13,
 streetViewControl: false // เป็นส่วนที่ Set เพิ่มเติมจากปกติ
 });

sv.getPanorama({ location: center_point, radius: 50 }, processSVData);

/***** กำหนด event เมื่อมีการคลิกแผนที่*****/
 map.addListener('click', function(event) {
 
/***** ล้างข้อมูลการกำหนดจุด เพื่อให้มีการกำหนดจุดพิกัดเพียงจุดเดียว*****/
 for (i = 0; i < markers.length; i++) {
 markers[i].setMap(null);
 }

/***** ดึงค่าข้อมูลจาก Street View ตามพิกัดที่คลิกบนแผนที่ *****/
 sv.getPanorama({ location: event.latLng, radius: 50 }, processSVData);
 var geocoder = new google.maps.Geocoder();
 geocoder.geocode({
 'latLng': event.latLng
 }, function(results, status) {
 if (status == google.maps.GeocoderStatus.OK) {

/***** แสดงผลข้อมูลรายละเอียดสถานที่*****/
 if (results[0]) {
    var place = results[0];
     for (var i = 0; i < place.address_components.length; i++) {
       if (place.address_components[i].types[0] == 'postal_code') {
         document.getElementById('postal_code').innerHTML = place.address_components[i].long_name;
      }
 if (place.address_components[i].types[0] == 'country') {
 document.getElementById('country').innerHTML = place.address_components[i].long_name;
    }
  }
 document.getElementById('location').innerHTML = results[0].formatted_address;
 document.getElementById('lat').innerHTML = results[0].geometry.location.lat();
 document.getElementById('lon').innerHTML = results[0].geometry.location.lng();
    }
   }
 });
 });
 /***** กำหนดตำแหน่งที่ตั้งของ control ที่จะวางในแผนที่*****/
 var input = document.getElementById('searchInput');
 map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

 /***** เพิ่ม Feature ให้กับ textbox ให้สามารถพิมพ์ค้นหาสถานที่ได้*****/
 var autocomplete = new google.maps.places.Autocomplete(input);
 autocomplete.bindTo('bounds', map);

 var infowindow = new google.maps.InfoWindow();
 
 /***** กำหนดคุณสมบัติให้กับตัวพิกัดจุดหรือ marker *****/
 var marker = new google.maps.Marker({
 map: map,
 anchorPoint: new google.maps.Point(0, -29)
 });
markers.push(marker); //เก็บค่าการกำหนดจุดพิกัดไว้ในตัวแปร markers เพื่อใช้ล้างข้อมูลการกำหนดจุดได้

 /***** ทำงานกับ event place_changed หรือเมื่อมีการเปลี่ยนแปลงค่าสถานที่ที่ค้นหา*****/
 autocomplete.addListener('place_changed', function() {
 infowindow.close();
 marker.setVisible(false);
 var place = autocomplete.getPlace();
 if (!place.geometry) {
 window.alert("ไม่ค้นพบพิกัดจากสถานที่ดังกล่าว");
 return;
 }

 /***** แสดงผลบนแผนที่เมื่อพบข้อมูลที่ต้องการค้นหา *****/
 if (place.geometry.viewport) {
 map.fitBounds(place.geometry.viewport);
 } else {
 map.setCenter(place.geometry.location);
 sv.getPanorama({ location: place.geometry.location, radius: 50 }, processSVData);
 map.setZoom(17);
 }
 marker.setIcon(({
 url: place.icon,
 size: new google.maps.Size(71, 71),
 origin: new google.maps.Point(0, 0),
 anchor: new google.maps.Point(17, 34),
 scaledSize: new google.maps.Size(35, 35)
 }));
 marker.setPosition(place.geometry.location);
 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[2] && place.address_components[2].short_name || '')
 ].join(' ');
 }
 /***** แสดงรายละเอียดผลลัพธ์การค้นหาเป็น popup โดยมีชื่อและสถานที่ดังกล่าว *****/
 infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
 infowindow.open(map, marker);

 /***** แสดงรายละเอียดผลลัพธ์การค้นหา ซึ่งประกอบด้วย ที่อยู่ รหัสไปรษณีย์ ประเทศ ละติจูดและลองจิจูด *****/
 for (var i = 0; i < place.address_components.length; i++) {
 if(place.address_components[i].types[0] == 'postal_code'){
 document.getElementById('postal_code').innerHTML = place.address_components[i].long_name;
 }
 if(place.address_components[i].types[0] == 'country'){
 document.getElementById('country').innerHTML = place.address_components[i].long_name;
 }
 }
 document.getElementById('location').innerHTML = place.formatted_address;
 document.getElementById('lat').innerHTML = place.geometry.location.lat();
 document.getElementById('lon').innerHTML = place.geometry.location.lng();
 });
}
</script>
  • ฟังก์ชั่น processSVData() เป็นฟังก์ชั่นที่ใช้ในการนำค่าของ Street view มาแสดงผล
<script>
function processSVData(data, status) {
 if (status === 'OK') {
 
  marker = new google.maps.Marker({
 position: data.location.latLng,
 map: map,
 title: data.location.description
 });
 markers.push(marker);
 panorama.setPano(data.location.pano);
 panorama.setPov({
 heading: 270,
 pitch: 0
 });
 panorama.setVisible(true);

 marker.addListener('click', function() {
 
 var markerPanoID = data.location.pano;
 // Set the Pano to use the passed panoID.
 panorama.setPano(markerPanoID);
 panorama.setPov({
 heading: 270,
 pitch: 0
 });
 panorama.setVisible(true);
 });
 } else {
 console.error('ไม่พบข้อมูล Street view ตามสถานที่ดังกล่าว');
 }
 }
</script>
  • ส่วนของการแสดงผล (ใน tag body)
<body>

<!--ส่วนของการแสดงรายละเอียดผลลัพธ์ที่ได้->
 <table style="width: 100%">
 <tr>
 <td>
<!--ส่วนของ Element ที่ใช้ในการแสดงผล->
 <input id="searchInput" class="controls" type="text" placeholder="Enter a location">
<div id="map" style="width: 60%;height:360px;float:left"></div>
<div id="pano" style="width: 40%;height:360px; float:left"> </div><br />
 </td>
 
 </tr>
 <tr>
 <td>
 <div id="Div1" style="width: 100%;" >
 <ul id="geoData">
 <li>ที่อยู่: <span id="location"></span></li>
 <li>รหัสไปรษณีย์ : <span id="postal_code"></span></li>
 <li>ประเทศ: <span id="country"></span></li>
 <li>ละติจูด: <span id="lat"></span></li>
 <li>ลองจิจูด: <span id="lon"></span></li>
</ul>
</div>

 </td>
 </tr>
 
 </table>
 <!--ส่วนของการประกาศค่าเริ่มต้นและตัวแปร รวมถึงการเรียกใช้งานฟังก์ชั่นเพื่อใช้ในการแสดงผลที่กล่าวไว้ก่อนหน้านี้-> <script> /***** function ในการประกาศค่าเริ่มต้นให้กับแผนที่ และอื่นๆตามที่กล่าวไว้แล้วข้างต้น*****/ </script> <!--สิ้นสุดส่วนของการประกาศค่าเริ่มต้นและตัวแปร รวมถึงการเรียกใช้งานฟังก์ชั่นเพื่อใช้ในการแสดงผล-> </body>

ผลลัพธ์ที่ได้

1. เมื่อเปิดหน้าจอขึ้นมา จะแสดงพิกัดที่จังหวัดกรุงเทพมหานครเป็นค่าตั้งต้น และฝั่งขวาเป็นภาพที่ดึงข้อมูลมาได้จากพิกัดดังกล่าวจากข้อมูล Street Views

2. พิมพ์ค้นหาชื่อสถานที่ และเลือกสถานที่ที่ต้องการ

3. เมื่อเลือกสถานที่เรียบร้อย จะมีการกำหนดพิกัดจุดตามชื่อสถานที่ที่เลือกไว้ และแสดงผลภาพจาก Street View รวมทั้งแสดงรายละเอียดในส่วนล่างของหน้าจอ ดังภาพ

       นอกจากการค้นหาพิกัดและข้อมูลภาพจาก Street View โดยใช้วิธีการพิมพ์ค้นหาแล้วนั้น ผู้ใช้ยังสามารถค้นหาพิกัดใหม่ได้จากการคลิกบนแผนที่ได้อีกด้วย ซึ่งจะแสดงผลลัพธ์ได้เช่นกัน ดังภาพ

       ผู้เขียนหวังเป็นอย่างยิ่งว่า บทความนี้จะช่วยเพิ่มประสิทธิภาพและเป็นอีกหนึ่งทางเลือกให้กับผู้พัฒนาได้หยิบยกวิธีการดึงค่าละติจูด-ลองจิจูดและการแสดงผลข้อมูลไปประยุกต์ใช้กับงานของแต่ละท่าน และอาจถือเป็นการเพิ่มลูกเล่นให้กับเว็บไซต์ของท่านให้มีความสามารถที่หลากหลายมากขึ้นเกี่ยวกับการใช้งานร่วมกับแผนที่ Google Maps หากผู้อ่านท่านใดมีข้อเสนอแนะหรือแนะนำวิธีเพิ่มเติมเกี่ยวกับเรื่องดังกล่าว ผู้เขียนยินดีเป็นอย่างยิ่งที่จะรับฟังและร่วมแบ่งปันความรู้ร่วมกันค่ะ หากบทความนี้มีส่วนผิดพลาดประการใด ผู้เขียนขออภัยไว้ ณ ที่นี้ด้วยค่ะ ^^

แหล่งข้อมูลอ้างอิง :  

https://www.tutorialspoint.com/google_maps/google_maps_symbols.htm

http://www.codexworld.com/autocomplete-places-search-box-google-maps-javascript-api/

      https://developers.google.com/maps/documentation/javascript/examples/streetview-service

Leave a Reply