โค้ดในเนื้อตอนนี้ เป็นการประยุกต์จากบทความเก่าเรื่อง
การใช้งาน polyline และ polygon ใน google map api v3
https://www.ninenik.com/content.php?arti_id=380 via @ninenik
รูป icon ประกอบ สามารถไปโหลดจากบทความด้านบนได้
การทำงานของโปรแกรมในบทความนี้คือ เมื่อเราคลิก ที่ icon ปุ่มสร้าง polygon
ในแผนที่แล้ว ก็จะสามารถ กดไปที่แผนที่ เพื่อวางจุด marker และเมื่อวาง marker
มากกว่าหรือเท่ากับ สามจุดขึ้นไป โปรแกรมก็จะสร้าง polygon กำหนดขอบเขต
ตามจุด marker ที่เราวาง โดยเราสามารถที่ย้ายตำแหน่ง ของจุดที่เรากำหนดได้
ค่า path ทั้งหมดจะแสดงใน textarea รายการด้านล่าง เราสามารถนำค่า submit
ไปบันทึกลงฐานข้อมูล เพื่อนำไปใช้ได้ รวมทั้ง ยังมีการคำนวน หาระยะทาง โดยรอบ
ของ polygon และ พืนที่ของ polygon อีกด้วย หากต้องการ reset เพื่อกำหนดค่าใหม่
ให้คลิกที่ icon รูปมือ มุมล่างซ้ายของแผนที่
ตัวอย่าง
โค้ด ggm_polygon.php
<?php // 3 บรรทัดนี้้ สำหรับป้องกันการ cache จำค่าเก่าตอนทพสอบ คงไว้ หรือเอาออกได้ header("Content-type:text/html; charset=UTF-8"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Polygon 01</title> <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">--> <link rel="stylesheet" href="bootstrap/css/bootstrap.css"> <style type="text/css"> html { height: 100% } body { height:100%; margin:0; padding:0; font-family:tahoma, "Microsoft Sans Serif", sans-serif, Verdana; font-size:12px; } /* css กำหนดความกว้าง ความสูงของแผนที่ */ #map_canvas { position:relative; width:550px; height:400px; margin:auto;/* margin-top:100px;*/ } #contain_map { position:relative; width:550px; height:400px; margin:auto; margin-top:10px; } /* css ของส่วนการกำหนดจุดเริ่มต้น และปลายทาง */ #showDD { position:absolute; bottom:5px; /* background-color:#000; */ color:#FFF; } #show_form_data { margin:auto; width:550px; } #hand_b { width:31px; height:31px; cursor:pointer; background-image: url(images/Bsu.png); } #hand_b.selected { background-image: url(images/Bsd.png); } #shape_b { width:31px; height:31px; cursor:pointer; background-image: url(images/Bpu.png); } #shape_b.selected { background-image: url(images/Bpd.png); } </style> </head> <body> <br> <div class="container-fluid"> <div id="contain_map"> <div id="map_canvas"></div> <div id="showDD"> <table> <tr> <td><div id="hand_b" onclick="stopEditing()"/></td> <td><div id="shape_b" onclick="startShape()"/></td> </tr> </table> </div> </div> <div id="show_form_data"> <form role="form" id="form_get_detailMap" name="form_get_detailMap" method="post" action=""> <div class="form-group col-xs-12"> <label for="path_arr">Path Array</label> <textarea class="form-control" name="path_arr" id="path_arr" cols="70" rows="4"></textarea> </div> <div class="form-group col-xs-6"> <label for="distance">Distance</label> <input class="form-control" name="distance" type="text" id="distance" value="" /> <span>km (หากเป็น poligon จะเป็นขนาดความยาวโดยรอบ)</span> </div> <div class="form-group col-xs-6"> <label for="area_data">Area</label> <input class="form-control" name="area_data" type="text" id="area_data" value="" /> <span>m<sup>2</sup> (หาร 1000000 จะได้ เท่ากับหน่วย km<sup>2</sup>)</span> </div> <div class="form-group col-xs-12"> <input type="submit" class="btn btn-primary" name="button" id="button" value="บันทึก" /> </div> </form> </div> </div> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//underscorejs.org/underscore-min.js"></script> <script type="text/javascript"> /* ส่วนสำหรับการ random ค่าสีและ event */ var COLORS =[ ["red", "#ff0000"], ["orange", "#ff8800"], ["green","#008000"], ["blue", "#000080"], ["purple", "#800080"] ]; var colorIndex_ = 0; var listener; /* ส่วนของการกำหนดค่า สำหรับคำนวณพื้นที่ */ var earthRadiusMeters=6367460.0; var metersPerDegree=2.0*Math.PI*earthRadiusMeters/360.0; var degreesPerRadian=180.0/Math.PI; var radiansPerDegree=Math.PI/180.0; var metersPerKm=1000.0; var map; // กำหนดตัวแปร map ไว้ด้านนอกฟังก์ชัน เพื่อให้สามารถเรียกใช้งาน จากส่วนอื่นได้ var GGM; // กำหนดตัวแปร GGM ไว้เก็บ google.maps Object จะได้เรียกใช้งานได้ง่ายขึ้น var poly; var polygon; var marker=[]; var Points=[]; var path=[]; var arr_path=[]; function swap_class(buttonId) { $("#hand_b").removeClass("selected"); $("#shape_b").removeClass("selected"); $("#"+buttonId).addClass("selected"); } function stopEditing() { swap_class("hand_b"); $("#path_arr").val(""); $("#distance").val(""); $("#area_data").val(""); if(listener!=undefined){ GGM.event.removeListener(listener); } if(polygon!=undefined){ console.log("IN"); path=[]; console.log("OUT"); console.log(path); polygon.setMap(null); } if(marker.length>0){ for(i=0;i<marker.length;i++){ marker[i].setMap(null); } } } function getColor(named) { return COLORS[(colorIndex_++) % COLORS.length][named ? 0 : 1]; } function getIcon(color) { var icon = new GIcon(); icon.image = "//google.com/mapfiles/ms/micons/" + color + ".png"; icon.iconSize = new GSize(32, 32); icon.iconAnchor = new GPoint(15, 32); return icon; } function startShape(){ swap_class("shape_b"); var color = getColor(true); var polygonOptions = { strokeColor: color, geodesic:true, strokeOpacity: 1.0, strokeWeight: 3, fillColor: color, fillOpacity: 0.35 } polygon = new GGM.Polygon(polygonOptions); polygon.setMap(map); startDrawing_polygon(polygon,color); } function startDrawing_polygon(polygon,color){ var i=0; var Points=[]; path = polygon.getPath(); var data_path=""; listener=GGM.event.addListener(map, 'click', function(event){ var val_latlng=[event.latLng.lat(),event.latLng.lng()]; // console.log(val_latlng[0]); // console.log(val_latlng[1]); path.push(event.latLng); Points.push(event.latLng); data_path+=val_latlng[0]+","+val_latlng[1]+"\r\n"; $("#path_arr").val(data_path); $("#distance").val(polygon.inKm()); calculateArea(Points); // Add a new marker at the new plotted point on the polyline. var image="//google.com/mapfiles/ms/micons/"+color+".png"; marker[i] = new GGM.Marker({ position: event.latLng, title: ""+i, draggable:true, map: map, icon: image }); GGM.event.addListener(marker[i], 'dragend', function(){ path=[]; var Points=[]; var data_path=""; polygon.setPath(path); path = polygon.getPath(); $.each(marker,function(m,n){ path.push(marker[m].getPosition()); Points.push(marker[m].getPosition()); var val_latlng=marker[m].getPosition(); data_path+=val_latlng.lat()+","+val_latlng.lng()+"\r\n"; }); calculateArea(Points); $("#path_arr").val(data_path); $("#distance").val(polygon.inKm()); }); i++; }); } function calculateArea(points) { if(points.length>2) { var areaMeters2=PlanarPolygonAreaMeters2(points); if(areaMeters2>1000000.0) areaMeters2=SphericalPolygonAreaMeters2(points); $("#area_data").val(areaMeters2.toFixed(2)); } } function PlanarPolygonAreaMeters2(points) { var a=0.0; for(var i=0;i<points.length;++i) {var j=(i+1)%points.length; var xi=points[i].lng()*metersPerDegree*Math.cos(points[i].lat()*radiansPerDegree); var yi=points[i].lat()*metersPerDegree; var xj=points[j].lng()*metersPerDegree*Math.cos(points[j].lat()*radiansPerDegree); var yj=points[j].lat()*metersPerDegree; a+=xi*yj-xj*yi;} return Math.abs(a/2.0); } function SphericalPolygonAreaMeters2(points) { var totalAngle=0.0; //alert(points[0]); for(i=0;i<points.length;++i) {var j=(i+1)%points.length; var k=(i+2)%points.length; totalAngle+=Angle(points[i],points[j],points[k]);} var planarTotalAngle=(points.length-2)*180.0; var sphericalExcess=totalAngle-planarTotalAngle; if(sphericalExcess>420.0) {totalAngle=points.length*360.0-totalAngle; sphericalExcess=totalAngle-planarTotalAngle;} else if(sphericalExcess>300.0&&sphericalExcess<420.0) {sphericalExcess=Math.abs(360.0-sphericalExcess);} return sphericalExcess*radiansPerDegree*earthRadiusMeters*earthRadiusMeters; } function Angle(p1,p2,p3) { var bearing21=Bearing(p2,p1); var bearing23=Bearing(p2,p3); var angle=bearing21-bearing23; if(angle<0.0) angle+=360.0; return angle; } function Bearing(from,to) { var lat1=from.lat()*radiansPerDegree; var lon1=from.lng()*radiansPerDegree; var lat2=to.lat()*radiansPerDegree; var lon2=to.lng()*radiansPerDegree; var angle=-Math.atan2(Math.sin(lon1-lon2)*Math.cos(lat2),Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2)); if(angle<0.0) angle+=Math.PI*2.0; angle=angle*degreesPerRadian; return angle; } function initialize() { // ฟังก์ชันแสดงแผนที่ GGM=new Object(google.maps); // เก็บตัวแปร google.maps Object ไว้ในตัวแปร GGM // กำหนดจุดเริ่มต้นของแผนที่ var my_Latlng = new GGM.LatLng(13.761728449950002,100.6527900695800); var my_mapTypeId=GGM.MapTypeId.ROADMAP; // กำหนดรูปแบบแผนที่ที่แสดง // กำหนด DOM object ที่จะเอาแผนที่ไปแสดง ที่นี้คือ div id=map_canvas var my_DivObj=$("#map_canvas")[0]; // กำหนด Option ของแผนที่ var myOptions = { zoom: 13, // กำหนดขนาดการ zoom center: my_Latlng , // กำหนดจุดกึ่งกลาง mapTypeId:my_mapTypeId // กำหนดรูปแบบแผนที่ }; map = new GGM.Map(my_DivObj,myOptions);// สร้างแผนที่และเก็บตัวแปรไว้ในชื่อ map GGM.LatLng.prototype.kmTo = function(a){ var e = Math, ra = e.PI/180; var b = this.lat() * ra, c = a.lat() * ra, d = b - c; var g = this.lng() * ra - a.lng() * ra; var f = 2 * e.asin(e.sqrt(e.pow(e.sin(d/2), 2) + e.cos(b) * e.cos (c) * e.pow(e.sin(g/2), 2))); return f * 6378.137; } GGM.Polyline.prototype.inKm = function(n){ var a = this.getPath(n), len = a.getLength(), dist = 0; for(var i=0; i<len-1; i++){ dist += a.getAt(i).kmTo(a.getAt(i+1)); } return dist; } GGM.Polygon.prototype.inKm = function(n){ var a = this.getPath(n), len = a.getLength(), dist = 0; var dist2=0; for(var i=0; i<len-1; i++){ dist += a.getAt(i).kmTo(a.getAt(i+1)); } dist2+=a.getAt(len-1).kmTo(a.getAt(0)); return dist+dist2; } } $(function(){ // โหลด สคริป google map api เมื่อเว็บโหลดเรียบร้อยแล้ว // ค่าตัวแปร ที่ส่งไปในไฟล์ google map api // v=3.2&sensor=false&language=th&callback=initialize // v เวอร์ชัน่ 3.2 // sensor กำหนดให้สามารถแสดงตำแหน่งทำเปิดแผนที่อยู่ได้ เหมาะสำหรับมือถือ ปกติใช้ false // language ภาษา th ,en เป็นต้น // callback ให้เรียกใช้ฟังก์ชันแสดง แผนที่ initialize $("<script/>", { "type": "text/javascript", src: "//maps.google.com/maps/api/js?v=3.2&sensor=false&language=th&callback=initialize" }).appendTo("body"); }); </script> </body> </html>