GoogleMap 結合資料庫在地圖上加入地標

GoogleMap 結合資料庫在地圖上加入地標

在藍色小舖上滿常看到的一個問題就是,如何從DB中撈取座標資料加在GoogleMap上。

雖然這是一個滿基本的功能,但也滿重要的。如果能自己寫出來,我想對於Ajax跟

Client與Server的觀念都有一定的認知,以後要利用此概念做出其他功能也不是難事了。

 

這篇文章就用實際的範例,來講解這個功能要怎麼做

 

本篇範例使用WebForm + 泛型處理常式 + jQuery AJAX + GoogleMap V3 來實作
  1. 新開一個Web Application
  2. 新增一個項目"泛型處理常式",取名為"GoogleMapHandler.ashx"

    image

    預設新增之後裡面會有一個屬性一個方法

            public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write("Hello World");
            }
    
            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }

    IsReusable指定IHttpHandler可否重用,通常都是false

    ProcessRequest是我們主要要處理的對象

  3. 測試案例假設需從前端接收一個Key,然後用此Key去資料去中撈出資料(經度、緯度以及地標名稱),再將撈出的資料以JSON格式傳回前端

 

在ProcessRequest中加入

            //傳進來的參數,可用這個去查詢資料庫
            var key = context.Request["key"];
            DataTable table = GetMapInfo(key);

拿到名稱為key的參數後,用GetMapInfo方法去資料庫撈取資料。

GetMapInfo可另外抽到別的檔案去實作,但此案例就在原檔案中作假資料

        /// <summary>
        /// 進資料庫查詢經緯度資料,並傳回DataTable
        /// </summary>
        private DataTable GetMapInfo(string key)
        {
            //如果需要用到key去資料庫查資料,請注意SQL Injection的問題
            //這邊的範例我就直接建假資料

            DataTable table = new DataTable();
            table.Columns.Add(new DataColumn("經度"));
            table.Columns.Add(new DataColumn("緯度"));
            table.Columns.Add(new DataColumn("Title"));

            DataRow dr = null;
            dr = table.NewRow();
            dr["經度"] = "121.517322";
            dr["緯度"] = "25.045831";
            dr["Title"] = "台北車站";
            table.Rows.Add(dr);

            dr = table.NewRow();
            dr["經度"] = "121.536076";
            dr["緯度"] = "25.030511";
            dr["Title"] = "大安森林公園";
            table.Rows.Add(dr);

            dr = table.NewRow();
            dr["經度"] = "121.564357";
            dr["緯度"] = "25.033506";
            dr["Title"] = "台北101";
            table.Rows.Add(dr);

            return table;
        }

 

 

以上Code做了三筆假資料,並回傳一個DataTable。

利用此DataTable的資料,組成JSON的格式回傳

            /*
               JSON 格式
               [{  key : value },{  key : value },{  key : value }]
            */
            int i = 0;
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            foreach (DataRow item in table.Rows)
            {
                i++;
                sb.Append("{");
                sb.AppendFormat("\"Title\": \"{0}\", \"Lng\": \"{1}\",\"Lat\": \"{2}\"",
                                item["Title"].ToString(),
                                item["經度"].ToString(),
                                item["緯度"].ToString()
                                );

                sb.Append("}");
                if (i < table.Rows.Count)
                    sb.Append(",");
            }
            sb.Append("]");

            context.Response.ContentType = "text/plain";
            //將此JSON格式的資料回傳
            context.Response.Write(sb.ToString());

到此,Server端程式就已經寫完了。

接著來寫Client端利用jQuery AJAX 呼叫泛型處理常式

1. 寫一個function來去呼叫GoogleMapHandler.ashx,並把座標加入Map中

        //參數map為地圖的實體
        function AddMark(map) {
            //用jQuery的Ajax,向GoogleMapHandler.ashx要求座標資料
            //更多用法請看jQuery API
            $.ajax({
                url: '/GoogleMapHandler.ashx',
                type: 'GET',
                data: { key: $('#map_key').val() },
                dataType: 'json',
                success: function (data, textStatus) {
                    for (var item in data) {
                        //建立經緯度座標
                        var myLatlng = new google.maps.LatLng(data[item].Lat, data[item].Lng);
                        //加一個Marker到map中
                        //更多用法可看Google Map API V3
                        var marker = new google.maps.Marker({
                            position: myLatlng,
                            map: map,
                            title: data[item].Title
                        }); 
                    }
                }
            });
        }

url:指定泛型處理常式的路徑

type:使用GET

data:名稱為key,值是ID為map_key的Textbox

dataType:json

succcess:當dataType為json時,此callback的function第一個參數data會使用JSON.parse()

來做轉換,假設我們回傳的json格式是 { 'Name' :  'CodingRoad' }的話 ,則用data.Name就可以取到值。

2. 在Windows onload的時候,加入地圖,並去呼叫GoogleMapHandler.ashx查到經緯度,

建立Marker加到Map之中

        function initialize() {
            var latlng = new google.maps.LatLng(25.030, 121.536);
            var myOptions = {
              zoom: 14,
              center: latlng,
              mapTypeId: google.maps.MapTypeId.ROADMAP
            };
          var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
          AddMark(map);
        }

        //Window Onload的時候加入地圖
        google.maps.event.addDomListener(window, 'load', initialize);

做出後的效果為:

image

 

貼上完整的Code

GoogleMapHandler.ashx

    /// <summary>
    ///GoogleMapHandler 的摘要描述
    /// </summary>
    public class GoogleMapHandler : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            //傳進來的參數,可用這個去查詢資料庫
            var key = context.Request["key"];
            DataTable table = GetMapInfo(key);

            /*
               JSON 格式
               [{  key : value },{  key : value },{  key : value }]
            */
            int i = 0;
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            foreach (DataRow item in table.Rows)
            {
                i++;
                sb.Append("{");
                sb.AppendFormat("\"Title\": \"{0}\", \"Lng\": \"{1}\",\"Lat\": \"{2}\"",
                                item["Title"].ToString(),
                                item["經度"].ToString(),
                                item["緯度"].ToString()
                                );

                sb.Append("}");
                if (i < table.Rows.Count)
                    sb.Append(",");
            }
            sb.Append("]");

            context.Response.ContentType = "text/plain";
            //將此JSON格式的資料回傳
            context.Response.Write(sb.ToString());
        }

        /// <summary>
        /// 進資料庫查詢經緯度資料,並傳回DataTable
        /// </summary>
        private DataTable GetMapInfo(string key)
        {
            //如果需要用到key去資料庫查資料,請注意SQL Injection的問題
            //這邊的範例我就直接建假資料

            DataTable table = new DataTable();
            table.Columns.Add(new DataColumn("經度"));
            table.Columns.Add(new DataColumn("緯度"));
            table.Columns.Add(new DataColumn("Title"));

            DataRow dr = null;
            dr = table.NewRow();
            dr["經度"] = "121.517322";
            dr["緯度"] = "25.045831";
            dr["Title"] = "台北車站";
            table.Rows.Add(dr);

            dr = table.NewRow();
            dr["經度"] = "121.536076";
            dr["緯度"] = "25.030511";
            dr["Title"] = "大安森林公園";
            table.Rows.Add(dr);

            dr = table.NewRow();
            dr["經度"] = "121.564357";
            dr["緯度"] = "25.033506";
            dr["Title"] = "台北101";
            table.Rows.Add(dr);

            return table;
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

 

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript">
        //參數map為地圖的實體
        function AddMark(map) {
            //用jQuery的Ajax,向GoogleMapHandler.ashx要求座標資料
            //更多用法請看jQuery API
            $.ajax({
                url: '/GoogleMapHandler.ashx',
                type: 'GET',
                data: { key: $('#map_key').val() },
                dataType: 'json',
                success: function (data, textStatus) {
                    for (var item in data) {
                        //建立經緯度座標
                        var myLatlng = new google.maps.LatLng(data[item].Lat, data[item].Lng);
                        //加一個Marker到map中
                        //更多用法可看Google Map API V3
                        var marker = new google.maps.Marker({
                            position: myLatlng,
                            map: map,
                            title: data[item].Title
                        }); 
                    }
                }
            });
        }

        function initialize() {
            var latlng = new google.maps.LatLng(25.030, 121.536);
            var myOptions = {
              zoom: 14,
              center: latlng,
              mapTypeId: google.maps.MapTypeId.ROADMAP
            };
          var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
          AddMark(map);
        }

        //Window Onload的時候加入地圖
        google.maps.event.addDomListener(window, 'load', initialize);
    </script>
</head>
<body>

    <form id="form1" runat="server">
        地圖參數:<input type="text" id="map_key" value="1" />
        <div id="map_canvas" style="width: 800px; height: 600px"></div>
    </form>
</body>
</html>

 

這是一個很基本的功能,但包含了一些基本功。

希望有幫助到問此問題的人。

!! 如果頁面有使用DOCTYPE的話!!
則GoogleMap的容器大小不能用style=”width:100%;height:100%;”這樣的方式指定;
必須設定明確的寬高,如style=”width:600px;height:400px;”