- 前言: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











