- 前言:Google Maps API 提供服務以來,由於容易開發、API功能多更新快並且又穩定,只要不踩到一些地雷,就不會收錢,所以一直是地圖開發者喜歡用的工具API。這一篇是要介紹,從資料庫取得點位資料套疊到地圖上。我使用的工具是 ASP.Net 使用 Google Map API v3 ,並且用AJAX,是因為如果用標準的asp.net button,會submit/postback 回 server,如果使用者在submit之前就做了一些地圖操作(放大、移動..),就會因為submit to server 會回到初始畫面,這樣的操作模式是滿令人不悅的,所以才需要AJAX方式來處理使用者對地圖的操作。
- 網頁功能:取得使用者目前座標,繪製地點與精確度的範圍。並根據使用者點選的圖層類型,帶入對應的點位。
- 瀏覽器限制:因為有用到HTML5,IE8,9確定不行,用 Chrome Ok, IPhone Safari OK
- 使用元件:
- Google Map API V3 :必要
- Visual Studio 2012:必要
- JQuery mobile:非必要,放著只為了可以在行動裝置上看。
- HTML5:必要,為了取得目前座標。所以..那個 IE
- 網頁主要分成 3 區
- (1)地圖區:顯示地圖
- (2) ASP.Net button 區:負責從資料庫取得資料,並呈現在地圖
- (3) JS Button區:主要是 javascript button,是操作google map的功能,如"取得目前位置"、"清除地圖" 這類的功能
- 以下列出比較重要的程式片段,完整的程式請到網頁最下方再去下載。
- HTML Head區:需要注意的是 style 那一區,因為 Google Map DIV必須指定大小,所以指定在Head裡面。其他就是引用 jquery 與 google map api v3
<head> <title>Google Maps API v3 and ASP.Net AJAX</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> html { height: 100% } body { height: 100%; margin: 0px; padding: 0px } #map_canvas { height: 100% } </style> <link rel="stylesheet" href="/css/jquery.mobile-1.2.0.min.css" /> <script src="/js/jquery-1.8.2.min.js"></script> <script src="/js/jquery.mobile-1.2.0.min.js"></script> <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
- 再下來就是控制google maps div 的區域,首先是global的變數
//Global variables var map; //地圖 var marker; //地圖上的點 var infowindow; //點上面跳出的視窗 var overlays = []; //目前地圖上所有套疊的圖層 var mapcenter = new google.maps.LatLng(25.228664, 121.750202); //預設的地圖中心
- 地圖初始化的function,等下會在body onload呼叫。裡面的詳細API 請參考Google 文件。在初始化完成後,呼叫 取得目前座標的function: getLocation。
function initialize() { var mapOptions = { zoom: 6, mapTypeId: google.maps.MapTypeId.ROADMAP, center: mapcenter, mapTypeControl: true, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, poistion: google.maps.ControlPosition.TOP_RIGHT, mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.TERRAIN, google.maps.MapTypeId.HYBRID, google.maps.MapTypeId.SATELLITE] }, navigationControl: true, navigationControlOptions: { style: google.maps.NavigationControlStyle.ZOOM_PAN }, scaleControl: true, disableDoubleClickZoom: false, streetViewControl: true, draggableCursor: 'move' }; infowindow = null; infowindow = new google.maps.InfoWindow({ content: "info window content" }); map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions); //取得使用者目前座標 getLocation(); }
- 取得目前位置化的function:使用HTML5的方式取得座標(點)與精確度(圓圈),並繪製到地圖上。
// //取得目前位置 // function getLocation() { var x = document.getElementById("Message"); if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition);
//如果要持續取得,用watchPosition//navigator.geolocation.watchPosition(showPosition); } else { x.innerHTML = "Geolocation is not supported by this browser."; } } function showPosition(position) { var x = document.getElementById("Message"); //x.innerHTML = "Latitude: " + position.coords.latitude + " Longitude: " + position.coords.longitude + " Accuracy" + position.coords.accuracy; var newMapCenter = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); map.setCenter(newMapCenter); //以marker方式出現 setMarker(newMapCenter, "My Current Location" + " Accuracy is :" + position.coords.accuracy); //以圓形出現 if (position.coords.accuracy != null) { DrawCircle(newMapCenter, position.coords.accuracy); if (position.coords.accuracy < 1000) { map.setZoom(14); } } else { DrawCircle(newMapCenter, 100); } }
- 繪圖用的function,繪製圓形、繪製單一點座標與視窗(infowindow)訊息
//繪製圓形 function DrawCircle(center,rad) { var draw_circle; draw_circle = new google.maps.Circle({ center: center, radius: rad, strokeColor: "#FF0000", strokeOpacity: 0.8, strokeWeight: 2, fillColor: "#FFFF00", fillOpacity: 0.35, map: map }); overlays.push(draw_circle); } //繪製單一點座標 function setMarker(singleCoord,infoWindowContent) { marker = new google.maps.Marker({ map: map, draggable: true, animation: google.maps.Animation.DROP, position: singleCoord }); google.maps.event.addListener(marker, 'click', function () { infowindow.setContent(infoWindowContent); infowindow.open(map, this); }); // overlays.push(marker); } //產生彈跳效果 function toggleBounce() { if (marker.getAnimation() != null) { marker.setAnimation(null); } else { marker.setAnimation(google.maps.Animation.BOUNCE); } }
- 繪製多個點,提供給asp.net程式呼叫。Javascript Array的格式是['Mount Evans', 59.32522, 18.17002, 4, 'This is Mount Evans.'];,C#要繪製多點的時候,就是去準備出這個多筆陣列,再交給 setMarkers 去繪製。
function setMarkers(markers) { for (var i = 0; i < markers.length; i++) { var sites = markers[i]; var siteLatLng = new google.maps.LatLng(sites[1], sites[2]); var marker = new google.maps.Marker({ position: siteLatLng, map: map, title: sites[0], zIndex: sites[3], html: sites[4] }); var contentString = "info window content"; google.maps.event.addListener(marker, "click", function () { infowindow.setContent(this.html); infowindow.open(map, this); if (marker.getAnimation() != null) { marker.setAnimation(null); } else { marker.setAnimation(google.maps.Animation.BOUNCE); } }); // overlays.push(marker); } }
- 清除全部繪製的圖層
function clearMarkers() { while (overlays[0]) { overlays.pop().setMap(null); } }
- 另外在.ASPX網頁設計上,只有ASPX的Controls(Button1~4,顯示A~D類的圖層資料),放在UpdatedPanel裡面。Google Map DIV 更要在Form 以外才能正常顯示。控制地圖的HTML Button(Button 6,7)則是單純的HTML button就可以
<div id="Message"></div> <div id="map_canvas" style="width:100%; height:80%"></div> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> AJAX Button:<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="All" /> <asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="A" /> <asp:Button ID="Button3" runat="server" OnClick="Button3_Click" Text="B" /> <asp:Button ID="Button4" runat="server" OnClick="Button4_Click" Text="C" /> <asp:Label ID="Label1" runat="server" Visible="False"></asp:Label> <br /> <asp:Label ID="lbErr" runat="server" Visible="False"></asp:Label> <br /> </ContentTemplate> </asp:UpdatePanel> JS Button: <input id="Button5" type="button" value="Find My Location" onclick="getLocation()"/><input id="Button6" type="button" value="Clear Markers" onclick="clearMarkers()" /></form>
- C#程式端,以Button3為例,這個按鈕的目的是取得B類的座標並繪製於地圖上
protected void Button3_Click(object sender, EventArgs e) { Label1.Text = System.DateTime.Now.ToLongTimeString(); Label1.Visible = true; string strJS = ""; ArrayList alMarkers = GetMarkers("B"); strJS = @"var sites = [" + String.Join(",", alMarkers.ToArray()) + "];setMarkers(sites);"; ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "alert", strJS, true); }
- C#程式端,GetMarkers的目的是從資料庫取出對應的
protected ArrayList GetMarkers(string strType) { ArrayList alMarkers = new ArrayList(); try { string conn = ConfigurationManager.ConnectionStrings["mydevConnectionString"].ConnectionString; using (SqlConnection connection = new SqlConnection(conn)) { connection.Open(); SqlCommand command = connection.CreateCommand(); command.Connection = connection; if (strType == "ALL") { command.CommandText = @"SELECT * FROM [MyDev].[dbo].[MyMap] with (nolock)"; } else { command.CommandText = @"SELECT * FROM [MyDev].[dbo].[MyMap] with (nolock) where Category=@Category"; command.Parameters.Add("@Category", SqlDbType.NVarChar, 20).Value = strType; } using (SqlDataReader dr = command.ExecuteReader()) { while (dr.Read()) { alMarkers.Add("['" + dr["Project"].ToString() + "', " + dr["Latitude"].ToString() + "," + dr["Longtitude"].ToString() + ", 1, '" + dr["Info"].ToString() + " " + dr["Addr"].ToString() + "']"); } } } } catch (Exception ex) { lbErr.Text = ex.ToString(); lbErr.Visible = true; } return alMarkers; }
- Table的設計很簡單,主要就是 Latitude(緯度), Longtitude(經度),其他都是輔助描述的欄位
CREATE TABLE [dbo].[MyMap]( [ID] [bigint] IDENTITY(1,1) NOT NULL, [Category] [nvarchar](20) NOT NULL, [Code] [nvarchar](20) NULL, [Info] [nvarchar](200) NULL, [Project] [nvarchar](50) NULL, [Addr] [nvarchar](100) NOT NULL, [Latitude] [float] NOT NULL, [Longtitude] [float] NOT NULL, [Coord] [geography] NULL ) ON [PRIMARY]
完成,結果如圖:
一進入網頁時,會直接定位目前座標,My Current Location 是我目前的座標,黃色是72公尺的精準度,其他的marker是點了B,帶入B類的座標,顯示在地圖上。
歡迎討論!
程式下載:
https://dl.dropbox.com/u/3330791/Sharecode/GoogleMapV3_ASPNET.rar
reference:
https://developers.google.com/maps/documentation/javascript/reference