百度地图热力图--批量地址转换应用(基于百度api)
需求:把外卖订餐地址做个用户分布热力图
思路分析:第一步去百度地图api开放平台找例子 http://lbsyun.baidu.com/jsdemo.htm#c1_15
首先从百度API的demo例子参考静态页面,其中数据格式是
然后我们就想把数据库里的地址批量转换但是百度API没有提供批量转换的接口。
但是我们找到了百度webapi单个地址转换的接口
利用这个接口,在后台读取地址和统计个数,返回一个json
用HttpWebRequest去发起get请求返回json,在把返回的json转成对象
这里套了三层,所以数据结构构造成这样(一开始不这么写获取是null)
单个地址转换写好了,下面用一个list<T>装一下,foreach遍历依次赋值,用个一般处理程序得到json
最后把前台界面的数组换成ajax请求数据,要把async设置成false同步请求,不然就会跳过这里往下执行,这里用匿名函数返回一个数组
最后结果
代码:
1 public static T RequestApi<T>(string address) 2 { 3 string apiUrl = "http://api.map.baidu.com/geocoder/v2/"; 4 string apiKey = "6Gra1QZ4gWrsrUgirWZ0Z1NdfFrh0mD3"; // 5 string output = "json"; 6 7 IDictionary<string, string> param = new Dictionary<string, string>(); 8 param.Add("ak", apiKey); 9 param.Add("output", output); 10 11 12 param.Add("address", address); 13 14 string result = string.Empty; 15 16 //初始化方案信息实体类。 17 T info = default(T); 18 try 19 { 20 //以 Get 形式请求 Api 地址 21 result = HttpUtils.DoGet(apiUrl, param); 22 info = JsonHelper.FromJson<T>(result); 23 } 24 catch (Exception) 25 { 26 info = default(T); 27 throw; 28 } 29 30 return info; 31 }
1 public class HttpUtils 2 { 3 /// <summary> 4 /// 执行HTTP GET请求。 5 /// </summary> 6 /// <param name="url">请求地址</param> 7 /// <param name="parameters">请求参数</param> 8 /// <returns>HTTP响应</returns> 9 public static string DoGet(string url, IDictionary<string, string> parameters) 10 { 11 if (parameters != null && parameters.Count > 0) 12 { 13 if (url.Contains("?")) 14 { 15 url = url + "&" + BuildPostData(parameters); 16 } 17 else 18 { 19 url = url + "?" + BuildPostData(parameters); 20 } 21 } 22 23 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); 24 req.ServicePoint.Expect100Continue = false; 25 req.Method = "GET"; 26 req.KeepAlive = true; 27 req.UserAgent = "Test"; 28 req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; 29 30 HttpWebResponse rsp = null; 31 try 32 { 33 rsp = (HttpWebResponse)req.GetResponse(); 34 } 35 catch (WebException webEx) 36 { 37 if (webEx.Status == WebExceptionStatus.Timeout) 38 { 39 rsp = null; 40 } 41 } 42 43 if (rsp != null) 44 { 45 if (rsp.CharacterSet != null) 46 { 47 Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet); 48 return GetResponseAsString(rsp, encoding); 49 } 50 else 51 { 52 return string.Empty; 53 } 54 } 55 else 56 { 57 return string.Empty; 58 } 59 } 60 61 /// <summary> 62 /// 把响应流转换为文本。 63 /// </summary> 64 /// <param name="rsp">响应流对象</param> 65 /// <param name="encoding">编码方式</param> 66 /// <returns>响应文本</returns> 67 private static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding) 68 { 69 StringBuilder result = new StringBuilder(); 70 Stream stream = null; 71 StreamReader reader = null; 72 73 try 74 { 75 // 以字符流的方式读取HTTP响应 76 stream = rsp.GetResponseStream(); 77 reader = new StreamReader(stream, encoding); 78 79 // 每次读取不大于256个字符,并写入字符串 80 char[] buffer = new char[256]; 81 int readBytes = 0; 82 while ((readBytes = reader.Read(buffer, 0, buffer.Length)) > 0) 83 { 84 result.Append(buffer, 0, readBytes); 85 } 86 } 87 catch (WebException webEx) 88 { 89 if (webEx.Status == WebExceptionStatus.Timeout) 90 { 91 result = new StringBuilder(); 92 } 93 } 94 finally 95 { 96 // 释放资源 97 if (reader != null) reader.Close(); 98 if (stream != null) stream.Close(); 99 if (rsp != null) rsp.Close(); 100 } 101 102 return result.ToString(); 103 } 104 105 /// <summary> 106 /// 组装普通文本请求参数。 107 /// </summary> 108 /// <param name="parameters">Key-Value形式请求参数字典。</param> 109 /// <returns>URL编码后的请求数据。</returns> 110 private static string BuildPostData(IDictionary<string, string> parameters) 111 { 112 StringBuilder postData = new StringBuilder(); 113 bool hasParam = false; 114 115 IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator(); 116 while (dem.MoveNext()) 117 { 118 string name = dem.Current.Key; 119 string value = dem.Current.Value; 120 // 忽略参数名或参数值为空的参数 121 if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) 122 { 123 if (hasParam) 124 { 125 postData.Append("&"); 126 } 127 128 postData.Append(name); 129 postData.Append("="); 130 postData.Append(Uri.EscapeDataString(value)); 131 hasParam = true; 132 } 133 } 134 135 return postData.ToString(); 136 } 137 138 }
1 public static class JsonHelper 2 { 3 private static JsonSerializerSettings _jsonSettings; 4 5 static JsonHelper() 6 { 7 IsoDateTimeConverter datetimeConverter = new IsoDateTimeConverter(); 8 datetimeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; 9 10 _jsonSettings = new JsonSerializerSettings(); 11 _jsonSettings.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore; 12 _jsonSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; 13 _jsonSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 14 _jsonSettings.Converters.Add(datetimeConverter); 15 } 16 17 /// <summary> 18 /// 将指定的对象序列化成 JSON 数据。 19 /// </summary> 20 /// <param name="obj">要序列化的对象。</param> 21 /// <returns></returns> 22 public static string ToJson(this object obj) 23 { 24 try 25 { 26 if (null == obj) 27 return null; 28 29 return JsonConvert.SerializeObject(obj, Formatting.None, _jsonSettings); 30 } 31 catch (Exception ex) 32 { 33 34 return null; 35 } 36 } 37 38 /// <summary> 39 /// 将指定的 JSON 数据反序列化成指定对象。 40 /// </summary> 41 /// <typeparam name="T">对象类型。</typeparam> 42 /// <param name="json">JSON 数据。</param> 43 /// <returns></returns> 44 public static T FromJson<T>(this string json) 45 { 46 try 47 { 48 return JsonConvert.DeserializeObject<T>(json, _jsonSettings); 49 } 50 catch (Exception ex) 51 { 52 53 54 return default(T); 55 } 56 } 57 }
最后结果:
1 public static IEnumerable<JWCDTO> GetAllJW() 2 { 3 List<BigDataDTO> p = GetAll().ToList(); 4 5 List<JWCDTO> list = new List<JWCDTO>(); ; 6 foreach (BigDataDTO pp in p) 7 { 8 string address = pp.Address; 9 int count = pp.count; 10 BGDTO bg = Re.RequestApi<BGDTO>(address); 11 if(bg==null) 12 { 13 continue; 14 } 15 string lat = bg.result.location.lat; 16 string lng = bg.result.location.lng; 17 JWCDTO log = ToProductDTO(lat, lng, count); 18 list.Add(log);//list.Add(ToLog(row)); 19 20 } 21 22 return list; 23 24 }
JW.ashx:
1 public class JW : IHttpHandler 2 { 3 4 public void ProcessRequest(HttpContext context) 5 { 6 context.Response.ContentType = "application/json"; 7 List<JWCDTO> p; 8 p = ReJson.GetAllJW().ToList(); 9 context.Response.Write(new JavaScriptSerializer().Serialize(p)); 10 } 11 12 public bool IsReusable 13 { 14 get 15 { 16 return false; 17 } 18 } 19 }
前台页面:
1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReJson.aspx.cs" Inherits="XZ.UI.Web.Admin.ReJson" %> 2 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 4 5 <html xmlns="http://www.w3.org/1999/xhtml"> 6 <head runat="server"> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 8 <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> 9 <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=1fReIR62vFbOc2vgrBnRAGyUtLkgoIIH"></script> 10 <script type="text/javascript" src="http://api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js"></script> 11 <script src="../Scripts/jquery-1.9.1.min.js" type="text/javascript"></script> 12 13 <title></title> 14 <style type="text/css"> 15 ul,li{list-style: none;margin:0;padding:0;float:left;} 16 html{height:100%} 17 body{height:100%;margin:0px;padding:0px;font-family:"微软雅黑";} 18 #container{height:700px;width:100%;} 19 #r-result{width:100%;} 20 </style> 21 </head> 22 <body> 23 <form id="form1" runat="server"> 24 <div> 25 <div id="container"></div> 26 <div id="r-result"> 27 <input type="button" onclick="openHeatmap();" value="显示热力图"/><input type="button" onclick="closeHeatmap();" value="关闭热力图"/> 28 </div> 29 </div> 30 </form> 31 </body> 32 </html> 33 34 <script type="text/javascript"> 35 var map = new BMap.Map("container"); // 创建地图实例 36 37 var point = new BMap.Point(118.906886, 31.895532); 38 map.centerAndZoom(point, 15); // 初始化地图,设置中心点坐标和地图级别 39 map.enableScrollWheelZoom(); // 允许滚轮缩放 40 41 if (!isSupportCanvas()) { 42 alert(\'热力图目前只支持有canvas支持的浏览器,您所使用的浏览器不能使用热力图功能~\') 43 } 44 45 heatmapOverlay = new BMapLib.HeatmapOverlay({ "radius": 20 }); 46 map.addOverlay(heatmapOverlay); 47 heatmapOverlay.setDataSet({ data: function () { 48 var serie = []; 49 $.ajax({ 50 url: "JW.ashx", 51 dataType: "json", 52 async: false, 53 success: function (dataJson) { 54 for (var i = 0; i < dataJson.length; i++) { 55 var item = { 56 lat: dataJson[i].lat, 57 lng: dataJson[i].lng, 58 count: dataJson[i].count 59 }; 60 serie.push(item); 61 } 62 } 63 }); 64 return serie; 65 } (), max: 100 }); 66 //是否显示热力图 67 function openHeatmap() { 68 heatmapOverlay.show(); 69 } 70 function closeHeatmap() { 71 heatmapOverlay.hide(); 72 } 73 closeHeatmap(); 74 function setGradient() { 75 /*格式如下所示: 76 { 77 0:\'rgb(102, 255, 0)\', 78 .5:\'rgb(255, 170, 0)\', 79 1:\'rgb(255, 0, 0)\' 80 }*/ 81 var gradient = {}; 82 var colors = document.querySelectorAll("input[type=\'color\']"); 83 colors = [].slice.call(colors, 0); 84 colors.forEach(function (ele) { 85 gradient[ele.getAttribute("data-key")] = ele.value; 86 }); 87 heatmapOverlay.setOptions({ "gradient": gradient }); 88 } 89 //判断浏览区是否支持canvas 90 function isSupportCanvas() { 91 var elem = document.createElement(\'canvas\'); 92 return !!(elem.getContext && elem.getContext(\'2d\')); 93 } 94 </script>