google map測距的實現和分析
不斷有傳聞google map在今年的7月1號之后在大陸停止運營,具體原因是因為天朝的牌照問題,這個就不多講了,可以發現現在搜房網的地圖,和安居客等的地圖紛紛都撤下 google map,而重新選擇了mapabc或baidu,當然網易房產地圖也不例外,現在也在使用mapabc作為網易房產地圖的開發,預計將在6月底前上線,到 時再跟大家分享一下mapabc的一些開發實踐。
還是說回google map的開發,自從上次建了個qq群就有不少人在問測距怎么實現,當然很多人想的是拿來主義的,當時是拿http://xf.house.163.com /gz/map/000B.html的例子出來,但確實頁面上進行了封裝也寫得比較亂,所以還是比較難以抽離,先給個簡單實現的例子:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=GBK"/>
<title>163網易房產</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var map;
function initialize() {
var myLatlng = new google.maps.LatLng(23.116193,113.374525);
var myOptions = {
zoom: 15,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
var polyline;
var polylinesArray = [];
//距離標記數組
var lenArray = [];
var rule = null;
//距離
function getDistance(){
//啟動整個地圖的click偵聽
rule = google.maps.event.addListener(map,"click",function(event){
addMarker(event.latLng);
});
}
//添加新標記
function addMarker(location){
//標記選項
var myOptions = {
position : location,
draggable :false,
map : map,
};
marker = new google.maps.Marker(myOptions);
//將標記壓入數組
lenArray.push(marker);
//計算距離
drawOverlay();
}
//畫出路徑覆蓋層
function drawOverlay(){
//路線數組
var flightPlanCoordinates = [];
//將坐標壓入路線數組
if (lenArray) {
for (i in lenArray) {
flightPlanCoordinates.push(lenArray[i].getPosition());
}
}
//路徑選項
var polylineOptions = {
path : flightPlanCoordinates,
map : map,
strokeColor : "#FF0000",
strokeOpacity : 1.0,
strokeWeight : 2
};
polyline = new google.maps.Polyline(polylineOptions);
//清除原有折線路徑
if (polylinesArray) {
for (i in polylinesArray) {
polylinesArray[i].setMap(null);
}
polylinesArray = [];
}
polyline.setMap(map);
polylinesArray.push(polyline);
alert((polyline.getLength()/1000).toFixed(3) + "km");
}
google.maps.LatLng.prototype.distanceFrom = function(latlng) {
var lat = [this.lat(), latlng.lat()]
var lng = [this.lng(), latlng.lng()]
var R = 6378137;
var dLat = (lat[1] - lat[0]) * Math.PI / 180;
var dLng = (lng[1] - lng[0]) * Math.PI / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat[0] * Math.PI / 180) * Math.cos(lat[1] * Math.PI / 180) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return Math.round(d);
}
google.maps.Marker.prototype.distanceFrom = function(marker) {
return this.getPosition().distanceFrom(marker.getPosition());
}
google.maps.Polyline.prototype.getLength = function() {
var d = 0;
var path = this.getPath();
var latlng;
for (var i = 0; i < path.getLength() - 1; i++) {
latlng = [path.getAt(i), path.getAt(i + 1)];
d += latlng[0].distanceFrom(latlng[1]);
}
return d;
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width: 500px; height: 400px"></div>
<a href="#this" onclick="getDistance();">開始測距</a>
</body>
</html>

例子給完了,其中測距的計算是抄了google的示例,想簡單拿來應用的到這里就可以結束了,還有點興趣的可以看看下面的簡單分析:
說到測距無非就是線的計算,根據google map api,測距的線性實現我們采用Polyline類,Polyline是折線是地圖上的連接線段的線性疊加層,擴展自MVCObject。
測距是由線組成,然后根據一組線的長短計算出線的啟動和終點線的距離,根據這個思路,我們定義出
var polyline;
var polylinesArray = [];
其中polyline是當前畫出來這條線,polylinesArray是一個數組,當每話出一條線就將這條線push到polylinesArray這個數組中去。
另外一條線其實是由兩個點,始點和終點所組成,所以我們也定義一個
var lenArray = [];
lenArray是一個數組,用來記錄鼠標點過的每一個點的信息
也就是說整個測距是由每一條線所組成,而一條線是由2個點組成。
思路理清楚了,接著一步一步看
當我們點擊了開始測距時,就需要啟動一個事件的監聽,對整個map的click事件監聽
rule = google.maps.event.addListener(map,"click",function(event){
addMarker(event.latLng);
});
當我們在地圖上進行點擊時,就會新增一個maker點,并且將這個maker壓入lenArray數組,以便于后面的計算
function addMarker(location){
...
marker = new google.maps.Marker(myOptions);
...
lenArray.push(marker);
drawOverlay();
接著會調用drawOverlay();使用polyline來畫線
var flightPlanCoordinates = [];
//將坐標壓入路線數組
if (lenArray) {
for (i in lenArray) {
flightPlanCoordinates.push(lenArray[i].getPosition());
}
}
var polylineOptions = {
path : flightPlanCoordinates,
map : map,
strokeColor : "#FF0000",
strokeOpacity : 1.0,
strokeWeight : 2
};
polyline = new google.maps.Polyline(polylineOptions);
其中polylineOptions的path參數是折線坐標的有序序列。可以使用一個簡單的 LatLng 數組或者 LatLng 的 MVCArray 指定此路徑。請注意,如果您傳
遞簡單的數組,則它會轉換為 MVCArray。在 MVCArray 中插入或刪除 LatLng 將自動更新地圖上的折線。
flightPlanCoordinates數組用于存儲在上面我們定義的lenArray數組的坐標值,每點擊一次就壓入一對坐標值。
strokeColor和strokeOpacity,strokeWeight是一些樣式的參數,如指定線條的寬度等等。
最后我們將定義的polyline進行setMap,在地圖上展現,并將polyline壓入到polylinesArray數組中去。
polyline.setMap(map);
polylinesArray.push(polyline);
到這里,線和點的展現已經完成了,接下來是需要將這些點線轉換成我們需要的距離值。
google.maps.Polyline.prototype.getLength = function() {
var d = 0;
var path = this.getPath();
var latlng;
for (var i = 0; i < path.getLength() - 1; i++) {
latlng = [path.getAt(i), path.getAt(i + 1)];
d += latlng[0].distanceFrom(latlng[1]);
}
return d;
}
這里需要講明的是this.getPath();它的說明是檢索第一條路徑。并且返回值是一組MVCArray.<LatLng>,也就是實際存儲了一條線的坐標值,在這里取出這些坐標的數組,并且進行循環distanceFrom計算
google.maps.LatLng.prototype.distanceFrom = function(latlng) {
var lat = [this.lat(), latlng.lat()]
var lng = [this.lng(), latlng.lng()]
var R = 6378137;
var dLat = (lat[1] - lat[0]) * Math.PI / 180;
var dLng = (lng[1] - lng[0]) * Math.PI / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat[0] * Math.PI / 180) * Math.cos(lat[1] * Math.PI / 180) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return Math.round(d);
}
這段計算實際上是抄自google map示例的,是將我們的坐標值轉換成我們需要計算的距離值,這里就不分析,有興趣可以玩玩,沒興趣就直接抄過去吧。
結果出來了,這個就是我們需要的測距的距離,當然你也可以用其他方式進行展現
alert((polyline.getLength()/1000).toFixed(3) + "km");只要閱讀google api和自己思路清楚,一個測距的demo很快就完成了,稍加裝飾基本就可以應用于生產上
如果你也在進行google map的開發,歡迎賜教和討論,建了個qq群:11029590