基于百度地图SDK和Elasticsearch GEO查询的地理围栏分析系统(3)-前端实现
转载自:http://www.cnblogs.com/Auyuer/p/8086975.html
MoonLight可视化订单需求区域分析系统实现功能:
在现实生活中,计算机和互联网迅速发展,人们越来越趋向于网络,于是我们就有了各种各样的系统,来帮助我们更好地生活。比如对于打车来说,我们也可以通过网上叫车,那么我们就会产生大量的用户订单,特别是对于一些固定时间、固定地点,叫车用户的订单量会非常大,那么我们同样也要很好的管理这些订单。那么我们便要采取某些策略来统计分析,比如我们可以使用区域化的管理方式,根据ES中的数据进行圈选定位,将所圈选出的部分订单再进行处理统计信息。那么为了能够更好地看到这些分析结果,我们对此提出了可视化的订单管理系统,结合ES索引,便可完成订单的可视化数据分析。
实现步骤:
为了安全将所有数据以及url接口隐去
- 首页展示如下图所示:
- 由于我们要在地图上做一定区域的圈选操作,首先我们应该引入百度地图:
代码如下:
- 首先百度地图有自己的API注册秘钥,使用之前登录官方网站自行申请即可
- 引入百度地图API注册秘钥、加载鼠标绘制工具、加载检索信息窗口、加载热力图图层等所需要的js (可查看百度地图官网)
1 <!-- 百度地图api注册秘钥 --> 2 <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak= "></script> 3 <!-- 加载鼠标绘制工具 --> 4 <script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"></script> 5 <!-- 加载检索信息窗口 --> 6 <script type="text/javascript" src="http://api.map.baidu.com/library/SearchInfoWindow/1.4/src/SearchInfoWindow_min.js"></script> 7 <!-- 加载热力图图层 --> 8 <script type="text/javascript" src="http://api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js"></script>
- 相关js代码如下:
1 var map = new BMap.Map('map_canvas');// 创建地图实例 2 var point = new BMap.Point(116.404, 39.915); // 天安门 3 map.centerAndZoom(point, 12);// 初始化地图,设置中心点坐标和地图级别 4 map.enableScrollWheelZoom();// 允许drawingManager.open()滚轮缩放
-
创建地图实例,设置地图中心位置,在这里我们以天安门为中心
- 同时我们允许鼠标滚轮缩放
- 页面绘制功能
首页左边栏为绘制功能区域以及热力图的开启关闭控制按钮区域:
绘制功能包括如下:画点、画圆、画折线、画多边形、画矩形,相应的控制右上角的绘制功能
热力图的开启和关闭:第一次点击时向后台发送请求,关闭按钮为红色,开启按钮为绿色,热力图主要分布于北京市
- 圈选操作
圈选操作由于主要有圆形圈选、矩形圈选、多边形圈选和折线圈选几种情况,那么对此我们应该分情况讨论:
代码如下:
1 var overlays = []; 2 //回调获得覆盖物信息 overlay是覆盖物的抽象基类 3 var overlaycomplete = function(e) { 4 overlays.push(e.overlay); 5 var result = ""; 6 result = "<p>"; 7 result += e.drawingMode + ":"; 8 if (e.drawingMode == BMAP_DRAWING_MARKER) { 9 result += ' 坐标:' + e.overlay.getPosition().lng + ',' + e.overlay.getPosition().lat; 10 11 //getPosition() 获取标签的经纬度坐标 lng lat 12 if ($('isInfowindow').checked) { 13 searchInfoWindow.open(e.overlay); 14 } 15 } 16 if (e.drawingMode == BMAP_DRAWING_CIRCLE) {
//圆形圈选,获得经纬度和半径 , 然后拼接到跳转向图标展示页面的url后面, 如 url_toPic所示,即可实现不同页面之间的参数传递
17 result += ' 半径:' + e.overlay.getRadius(); 18 result += ' 中心点:' + e.overlay.getCenter().lng + "," + e.overlay.getCenter().lat; 19 var circle_r = e.overlay.getRadius(); 20 var circle_lng = e.overlay.getCenter().lng; 21 var circle_lat = e.overlay.getCenter().lat; 22 var url_toPic = "url?point=" + circle_lat + "," + circle_lng + "&radius=" + circle_r; 23 24 /* 向后台发送post请求 地理围栏数据*/ 25 // 圈选之后会自动跳出一个弹窗,用于可以自行保存相应的数据,自行设置名称和分组,而地理围栏geo和类型则是根据用户全选情况而自动添加。
26 // jQuery("#fence_name").val(name); 27 jQuery("#geo_data").css({ 28 "display":"block" 29 }); //弹窗显示 30 /*中间层*/ 31 jQuery("#cover").css({ 32 "display":"block" 33 }); //中间禁止点击层显示 34 var fence_circle_data; 35 fence_circle_data='{"circle":"'+circle_r+'","circle_lat":"'+circle_lat+'","circle_lng":"'+circle_lng+'"}'; 36 //地理围栏geo数据拼接和填充 37 jQuery("#fence_geo").val(fence_circle_data); 38 /*圆形1*/ 39 40 jQuery("#fence_type").val("1"); 41 42 //当点击弹窗的保存按钮时,则会将此次圈选信息保存起来,并存储在地理围栏中,方便后续查询,然后自动跳转到图表展示页面,图表展示页面主要是对订单量、日盈里和取消率的数据的具体展示 43 //从中,我们能够看到整个月份的订单量、日盈里和取消率的折线趋向,同时下方表格中也将所展示的具体数据填入。如果在弹窗页面出现时,用户没有填入名称和分组,那么我们就会给其名称设定为当前的时间戳加上三位随机数,而默认分组设为default。 44 jQuery("#btn_yes").click(function(){ 45 /*获取当前时间戳*/ 46 var data_time = new Date().getTime(); 47 /*获取0-1000之间的随机数*/ 48 var data_random = Math.ceil(Math.random()*1000); 49 /*拼接默认弹窗名称*/ 50 var name = "fence-"+data_time+data_random; 51 /*控制name group的默认传参*/ 52 var name_send; 53 var group_send ; 54 56 if(jQuery("#fence_name").val() != ""){ 57 name_send = jQuery("#fence_name").val(); 58 }else{ 59 name_send = name; 60 }; 61 if(jQuery("#fence_group").val() != ""){ 62 group_send = jQuery("#fence_group").val(); 63 }else{ 64 group_send = "default"; 65 } 66 67 68 var post_data =new Object; 69 post_data.name=name_send; 70 post_data.group=group_send; 71 post_data.type=jQuery("#fence_type").val(); 72 post_data.geo=jQuery("#fence_geo").val(); 73 var saveData = JSON.stringify(post_data); 74 75 send_post("url",saveData); 76 window.open(url_toPic,"_self"); 77 }); //如果用户点击了取消按钮没有保存数据,那么弹窗隐藏之后便会直接跳转至图表展示页面而不会存储本地圈选信息至地理围栏数据中。 78 jQuery("#btn_no").click(function(){ 79 jQuery("#geo_data").css({ 80 "display":"none" 81 }); 82 jQuery("#cover").css({ 83 "display":"none" 84 }); 85 window.open(url_toPic,"_self"); 86 }) 87 } 88 89 if (e.drawingMode == BMAP_DRAWING_POLYLINE || e.drawingMode == BMAP_DRAWING_POLYGON || e.drawingMode == BMAP_DRAWING_RECTANGLE) { 90 //在这里为折线、多边形、矩形等多点圈选,将所画出的点依次拼接到Url后面 方法同圆形圈选 91 166 }); 167 176 177 } 178 179 };
- 保存地理围栏数据弹窗:
- 图表展示页面为echarts表格和折线图 (为了安全将实际数据隐去)
4.图表展示页面前端实现相关代码如下:
1 //将所传递过来的url后的参数解析绘制图表 2 /*获取url参数*/ 3 function getUrlParam(){ 4 /*拿到url地址*/ 5 var url=window.location.search; 6 /*截取?后的所有数据*/ 7 var params = url.substring(url.indexOf("?")+1); 8 /*如果url中有弧度的数据*/ 9 var str='radius'; 10 var json_data; 11 /*获取圆形圈选的经纬度和弧度*/ 12 if(url.indexOf(str)!=-1){ 13 var paramArr=params.split("&"); 14 var param_first=paramArr[0].split("="); 15 var param_lng_lat=param_first[1].split(","); 16 var circle_lat = param_lng_lat[0]; 17 var circle_lng = param_lng_lat[1]; 18 var param_second = paramArr[1].split("="); 19 var circle_r = param_second[1]; 20 21 /*请求后端接口*/ 22 json_data=send_get("url?point=" + circle_lat + "," + circle_lng + "&radius=" + circle_r); 23 24 }else{ 25 /*截取url中等号右边的参数*/ 26 var paramSqual=params.split("="); 27 var paramSqual_lng_lat; 28 var url_getSqual; 29 url_getSqual="url?"; 30 /*参数列表为用;分割开的经纬度数据*/ 31 var paramSqual_Arr = paramSqual[1].split(";"); 32 for(var i=0;i<paramSqual_Arr.length;i++){ 33 paramSqual_lng_lat=paramSqual_Arr[i].split(","); 34 url_getSqual+="point"+i+"="+paramSqual_lng_lat[0]+','+paramSqual_lng_lat[1]+'&'; 37 } 38 url_getSqual=url_getSqual.substring(0,url_getSqual.length-1); 39 json_data=send_get(url_getSqual); 40 41 }
相关图表echarts代码展示如下:
以订单量为例,其他折线图代码类似。 具体使用方法建议查看Echarts官方网站
1 /*渲染图表*/ 2 3 /*日订单量图表展示区*/ 4 var chartName_total = echarts.init(document.getElementById("chart_total")); 5 var adata_total=json_data.data; 6 var option_total = { 7 title: { 8 text: '订单量分析' 9 }, 10 tooltip: { 11 trigger: 'axis' 12 }, 13 legend: { 14 data:['订单量'] 15 }, 16 grid: { 17 left: '3%', 18 right: '4%', 19 bottom: '3%', 20 containLabel: true 21 }, 22 toolbox: { 23 feature: { 24 saveAsImage: {} 25 } 26 }, 27 xAxis: { 28 type: 'category', 29 boundaryGap: false, 30 data:adata_total["xAxis"] 31 }, 32 yAxis: { 33 type: 'value' 34 }, 35 series: [ 36 { 37 name: '订单数量', 38 type: 'line', 39 stack: '总量', 40 data: adata_total["total"] 41 } 42 ] 43 }; 44 chartName_total.setOption(option_total);
表格中的数据展示代码: 也可使用其他方式渲染
/*表格中的数据*/ var tableData =json_data.data.detail; var tableSource="<table id='example' class='table table-striped table-bordered'>"
+ "<thead><tr><th>日期</th> <th>订单总量</th> <th>日盈利</th> <th>取消率</th></tr></thead><tbody>"; for(var j=0;j<tableData.length;j++){ tableSource+="<tr><th style='font-weight:normal'>"
+tableData[j].date
+"</th><th style='font-weight:normal'>"
+tableData[j].total
+"</th><th style='font-weight:normal'>"
+tableData[j].profit
+"</th><th style='font-weight:normal'>"
+tableData[j].cancelRatio; } tableSource +="</tbody><tfoot><tr> <th>日期</th> <th>订单总量</th> <th>日盈利</th> <th>取消率</th> </tr> </tfoot></table>"; $("#container").append(tableSource);
5.地理围栏数据存储页面
所有被圈选的数据都会在这里进行存储,当我们点击查看按钮时,则可再次查看相应地理围栏信息数据的图表展示,而点击删除并且确认删除之后,则会直接将此条数据删除。
查询按钮即可根据相应的条件筛选而取得符合条件的数据。
(1)查看和删除按钮的代码如下:
1 //删除和查看数据代码 2 //点击删除按钮时,将该行数据删除,并且调用后端接口,删除后端数据 3 function delete_data(){ 4 $(".btn_delete").click(function(){ 5 if(confirm("是否确认删除?")){ 6 $(this).parents("tr").remove(); 7 var delete_id=$(this).parents("tr").children("th.delete_id").text(); //先找到父元素,再找父元素中需要的子元素 8 var url_delete; 9 url_delete="url?id="; 10 url_delete+=delete_id; 11 var delete_data=send_get(url_delete); 12 alert(delete_data.message); 13 }else{ 14 return false; 15 } 16 }); 17 18 //点击查看按钮时,将url拼接对应经纬度数据等,然后跳转到图表展示页面并且进行利用所传递的参数进行图表绘制,圆形圈选需要的是中心点和半径,而其他都是将各个点的经纬度依次拼接即可。 19 $(".btn_look").click(function(){ 20 var jsonStr=$(this).parents("tr").children("th.tabData_geo").text(); 21 console.log($(this).parents("tr").children("th.tabData_geo").text()); 22 var json=$.parseJSON(String(jsonStr)); 23 console.log(json); 24 var look_url; 25 var num=0; 26 var jsonType=$(this).parents("tr").children("th#fence_type").text(); 27 if(jsonType == "环形") { 28 look_url= "url?point=" + json.circle_lat + "," + json.circle_lng + "&radius=" + json.circle; 29 window.open(look_url,"_self") 30 }else { 31 look_url= "url?point="; 32 for(var i=0;i<json.length;i++){ 33 for(var j in json[i]) { 34 num++; 35 look_url+=json[i][j]; 36 if(num%2==0) { 37 look_url+=";"; 38 }else { 39 look_url+=","; 40 } 41 } 42 } //根据自己的需要拼接字符串url 43 look_url=look_url.substring(0,look_url.length-1); 44 window.open(look_url , "_self") 45 } 46 }); 47 }
(2)表格绘制部分代码:
1 //该表格绘制部分分为不同情况,比如我们刚一打开页面时, 2 //要向后端默认传递页码为1,而所拿到的数据是全部数据。 3 //而当我们点击了查询按钮之后,所拿到的数据多少又会发生变化 4 //向后端传递的字段为page_json ,代码中即可看到具体的内容 5 function tabData_show(){ 6 7 var json_data; 8 var page_json = { 9 "name": null, 10 "group": null, 11 "type": null, 12 "startTime": null, 13 "endTime": null, 14 "pageSize": 10||null, 15 "pageNum": 1||null 16 }; 17 page_json = JSON.stringify(page_json); 18 json_data = send_post("url",page_json); 19 var tabData = json_data.data.data; 20 21 var totle_Page = Math.ceil(json_data.data.total/10); 22 var now_Page = json_data.data.nowPage; 23 var page_Limit = Math.min(9 , totle_Page); 24 //nowPage=now_Page; 25 //maxPage=totle_Page; 26 page(now_Page,totle_Page , page_Limit); 27 /*地理围栏表格*/ 28 …… 29 //接下来根据数据自行渲染表格即可
}
(3)查询部分代码:
1 /*search按钮点击时的搜索功能*/ 2 //查询按钮点击的时候,没有添加过滤条件时默认返回所有数据进行渲染 3 //而如果有过滤条件时则根据筛选条件返回相应的数据 4 $(".search").click(function () { 5 $("#page-item a.page-link").remove(); 6 var search_type; 7 if($("#btn_search_type").val() == "环形") { 8 search_type = 1; 9 }else if($("#btn_search_type").val() == "矩形") { 10 search_type = 2; 11 }else{ 12 search_type = 3; 13 } 14 var search_json = { 15 "name": $("#btn_search_name").val() || null, 16 "group": $("#btn_search_group").val() || null, 17 "type": search_type || null, 18 "startTime": $("#btn_search_start").val() || null, 19 "endTime": $("#btn_search_end").val() || null, 20 "pageSize": 10 || null, 21 "pageNum": 1 || null 22 }; 23 search_json = JSON.stringify(search_json); 24 25 var data_Json = send_post("url", search_json); 26 var dataJson = data_Json.data.data; 27 var totle_search = Math.ceil(data_Json.data.total / 10); 28 var search_Page = data_Json.data.nowPage; 29 var search_Limit = Math.min(9, totle_search); 30 page(search_Page, totle_search, search_Limit); 31 32 //然后再根据新拿到的不同数据渲染表格 49 });
到此 地理围栏的前端实现方法基本结束,后续不断改进中。