基于PetShop的数据可视化网站(三):可视化插件
2016-02-04 21:20
681 查看
在之前的系列中,我们可以较为轻松的将数据提取出来,但是仅仅使用表格等形式十分不直观。本文将通过百度地图API和ECharts对数据进行绘图。
具体的项目文件可以参考我的github仓库
在之前的系列中,我们将设备信息提取到了表现层,那么我们可以在aspx.cs后台中将得到的值包装成固定格式传输给aspx页面,这时得到了如图的效果,具体代码如下所示
BaiduMapClick.aspx
当时曾经尝试打开地图的时候开启所有信息窗口,但是根据实际使用,发现每次只能出现一个信息窗口气泡,遂放弃。
BaiduMapClick.aspx.cs
其实际效果如下所示:
在这里,我仅仅是使用其绘制了两条简单的曲线,来反映设备读取到的数据,这是我将百度API和repeater插件以及ECharts集合起来使用的代码:
Default.aspx
内容大体上和之前都是重复的,除了ECharts数据推送部分,是将后台得到的数据一个个的push到图中,由于后台提取的数据是逆序,在BLL中并没有找到List的Reverse方法,因此直接在前台逆序push。
Default.aspx.cs
大体的处理过程:进入页面后首先绘制地图;接下来判断URL中是否包含DeviceID,如果没有,默认为1,否则查询相应Device的数据并放入repeater中;最后提取该设备的数据,绘制曲线图。
具体的项目文件可以参考我的github仓库
百度地图API
地图的作用是展现一块儿区域内容或寻径,项目为了展现设备所处地点,引用百度地图API进行展示。大体效果如下:在之前的系列中,我们将设备信息提取到了表现层,那么我们可以在aspx.cs后台中将得到的值包装成固定格式传输给aspx页面,这时得到了如图的效果,具体代码如下所示
BaiduMapClick.aspx
[code]<%@ Page Language="C#" AutoEventWireup="true" CodeFile="BaiduMapClick.aspx.cs" Inherits="BaiduMapClick" %> <!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"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html,#allmap {width: 800px;height: 600px;overflow: hidden;margin:0;font-family:"微软雅黑";} </style> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的ak码"></script> <title></title> </head> <body> <form id="form1" runat="server"> <div id="allmap"></div> </form> </body> </html> <script type="text/javascript"> // 百度地图API功能 // 创建Map实例 var map = new BMap.Map("allmap"); // 初始化地图,设置中心点坐标和地图级别 var point = new BMap.Point(120.277515, 31.490646); map.centerAndZoom(point, 18); //开启鼠标滚轮缩放 map.enableScrollWheelZoom(true); //mapdata是后台传送过来的内容,结构大概这样: //[[116.417854,39.921988,1,"Arduino Uno"], //[116.406605,39.921585,2,"Virtual Device"]] var json_data = <%= mapdata %>; var pointArray = new Array(); for (var i = 0; i < json_data.length; i++) { // 创建点 var marker = new BMap.Marker(new BMap.Point(json_data[i][0], json_data[i][1])); //增加点 map.addOverlay(marker); //这个是给点加标签,但是单击事件还是在点上面 var strdesc = "设备" + json_data[i][2] + ":" + json_data[i][3] var label = new BMap.Label(strdesc, { offset: new BMap.Size(20, -10) }); //这里Title存储的是DeviceID marker.setTitle(json_data[i][2]); marker.setLabel(label); pointArray[i] = new BMap.Point(json_data[i][0], json_data[i][1]); //为每一个点增加一个单击事件 marker.addEventListener("click", function(e){ChangeLabel(e)}); } //让所有点在视野范围内 map.setViewport(pointArray); //点击marker之后调用的函数,初步理解为改变隐藏的label里面的值,然后在刷新本页的方法 function ChangeLabel(e) { //这里获得了DeviceID var p = e.target; var devicenum = p.getTitle(); // 这里设置了转向页面,来提交我们点击的DeviceID window.location.href = 'BaiduMapClick.aspx?devicenum='+devicenum; } </script>
当时曾经尝试打开地图的时候开启所有信息窗口,但是根据实际使用,发现每次只能出现一个信息窗口气泡,遂放弃。
BaiduMapClick.aspx.cs
[code]using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using FWSync.BLL; using FWSync.Model; using FWSync.Web; public partial class BaiduMapClick : System.Web.UI.Page { //设置一个全局变量,存储DeviceID public int devicenum = 1; //设置一个string记录需要返回到前台的值 public string mapdata = ""; protected void Page_Load(object sender, EventArgs e) { //使用缓存依赖调取所有设备信息 IList<DeviceInfo> devicedata = DeviceDataProxy.GetDevices(); //这里往下都是在拼凑前台需要的mapdata串 mapdata = "["; if (devicedata.Count > 0) { for(int i = 0 ; i < devicedata.Count ; i++) { mapdata += "[" + devicedata[i].DeviceX + "," + devicedata[i].DeviceY + "," + devicedata[i].DeviceID + "," + "\"" + devicedata[i].DeviceDesc + "\"],"; } } //去掉逗号 mapdata = mapdata.TrimEnd(','); mapdata += "]"; //这里是每次进入页面后查看URL中是否将DeviceID传递过来 if (this.Request["devicenum"] != null) { int devicenum = int.Parse(HttpUtility.HtmlEncode(this.Request["devicenum"])); } } }
ECharts
ECharts是百度团队开发的一个数据可视化插件,其功能较为强大,能够实现各种刁钻图形的绘制。如果使用过Highcharts会有非常熟悉的感觉。其主要的入门操作可以看这里其实际效果如下所示:
在这里,我仅仅是使用其绘制了两条简单的曲线,来反映设备读取到的数据,这是我将百度API和repeater插件以及ECharts集合起来使用的代码:
Default.aspx
[code]<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_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 id="Head1" runat="server"> <title>首页</title> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的ak码"></script> <script type="text/javascript" src="./JS/echarts.common.min.js"></script> </head> <body> <form id="form1" runat="server"> <div> //登录控件 <asp:LoginName ID="LoginName1" runat="server" /> <asp:LoginStatus ID="LoginStatus1" runat="server" LogoutAction="RedirectToLoginPage" /> </div> <div id="allmap" style="width: 600px;height:400px;"></div> <br /> <br /> <br /> 这里需要根据列表选择哪个参数,通过repeater点击某一行然后刷新并绑定数据来实现 <br /> <asp:Repeater ID="rpt" runat="server" > <HeaderTemplate> <table> <tr> <td> 设备名称 </td> <td> 设备值 </td> <td> 采集时间 </td> </tr> </HeaderTemplate> <ItemTemplate> <tr> <td > <asp:Label ID = "lblName" runat ="server" Text='<%# DataBinder.Eval(Container.DataItem, "ParamDesc") %>'></asp:Label> </td> <td > <asp:Label ID = "lblValue" runat ="server" Text='<%# DataBinder.Eval(Container.DataItem, "ParamValue") %>'></asp:Label> </td> <td > <asp:Label ID = "lblTime" runat ="server" Text='<%# DataBinder.Eval(Container.DataItem, "InsertTime") %>'></asp:Label> </td> </tr> </ItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> <br /> <br /> 这里需要有图像,折线图什么的 <div id="container" style="width: 600px;height:400px;"> </div> <script type="text/javascript"> // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('container')); // 指定图表的配置项和数据 option = { tooltip: { trigger: 'item', formatter: function (params) { var date = new Date(params.value[0]); date = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes(); return '时间:' + date + '<br/>'+ '参数值: ' + params.value[1] ; } }, legend: { data: ['温度','一氧化碳'] }, grid: { containLabel: true }, xAxis: [ { type: 'time' } ], yAxis: [ { type: 'value', scale:true } ], series: [ { name:'温度', type:'line', smooth: true, data:(function (){ var res = []; //这里得到了后台数据,但是推送数据是倒着推送的,是因为获得的数据是反过来的 var jsonData = <%= jsonstr %>; var i; var now = new Date(); for (i = 0; i < jsonData.j; i++) { res.push([ now.setTime(jsonData.rows[ jsonData.j - i-1].time1), jsonData.rows[ jsonData.j - i-1].price ]); } return res; })() }, { name:'一氧化碳', type:'line', smooth: true, data:(function (){ var res = []; var jsonData = <%= jsonstr2 %>; var i; var now = new Date(); for (i = 0; i < jsonData.j; i++) { res.push([ now.setTime(jsonData.rows[ jsonData.j - i-1].time1), jsonData.rows[ jsonData.j - i-1].price ]); } return res; })() } ] };//end option // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); </script> </form> </body> </html> <script type="text/javascript"> // 百度地图API功能 var map = new BMap.Map("allmap"); var point = new BMap.Point(120.277515, 31.490646); map.centerAndZoom(point, 18); map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放 var json_data = <%= mapdata %>; var pointArray = new Array(); for (var i = 0; i < json_data.length; i++) { var marker = new BMap.Marker(new BMap.Point(json_data[i][0], json_data[i][1])); // 创建点 map.addOverlay(marker); //增加点 //这个是给点加标签,但是单击事件还是在点上面 var strdesc = "设备" + json_data[i][2] + ":" + json_data[i][3] var label = new BMap.Label(strdesc, { offset: new BMap.Size(20, -10) }); marker.setTitle(json_data[i][2]); marker.setLabel(label); pointArray[i] = new BMap.Point(json_data[i][0], json_data[i][1]); marker.addEventListener("click", function(e){ChangeLabel(e)}); } //让所有点在视野范围内 map.setViewport(pointArray); //点击marker之后调用的函数,初步理解为改变隐藏的label里面的值,然后在刷新本页的方法 function ChangeLabel(e) { var p = e.target; var devicenum = p.getTitle(); // 这里设置了转向页面,使用了get请求,如果没有这个的话,那么设定一个默认值好了 window.location.href = 'Default.aspx?devicenum='+devicenum; } </script>
内容大体上和之前都是重复的,除了ECharts数据推送部分,是将后台得到的数据一个个的push到图中,由于后台提取的数据是逆序,在BLL中并没有找到List的Reverse方法,因此直接在前台逆序push。
Default.aspx.cs
[code]using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using FWSync.BLL; using FWSync.Model; using FWSync.Web; public partial class _Default : System.Web.UI.Page { //地图要用到的内容 public int deviceid = 1; public string mapdata = ""; //js作图用这个串来传递数据 public string jsonstr = ""; public string jsonstr2 = ""; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { //基于票据的验证方法 //如果登录,则显示用户名 HttpContext context = this.Context; System.Security.Principal.IPrincipal; System.Security.Principal.IPrincipal user = this.User; } //这里应该是每次进来都做得事情,即对数据进行绑定 //首先对表格进行调整 BindAll(); } private void BindAll() { IList<DeviceInfo> devicedata = DeviceDataProxy.GetDevices(); mapdata = "["; if (devicedata.Count > 0) { for (int i = 0; i < devicedata.Count; i++) { mapdata += "[" + devicedata[i].DeviceX + "," + devicedata[i].DeviceY + "," + devicedata[i].DeviceID + "," + "\"" + devicedata[i].DeviceDesc + "\"],"; } } mapdata = mapdata.TrimEnd(','); mapdata += "]"; if (this.Request["devicenum"] != null) { deviceid = int.Parse(HttpUtility.HtmlEncode(this.Request["devicenum"])); } //这里通过获得的DeviceID提取数据 IList<ParamAndOneDataInfo> tempdata = WebUtility.GetParamAndOneData(deviceid); rpt.DataSource = tempdata; rpt.DataBind(); //接下来对折线进行调整 jsonstr = GetLine(deviceid, 1); jsonstr2 = GetLine(deviceid, 2); } //GetLine这个方法是通过DeviceID和ParamID获得数据,并返回一个拼凑的string private string GetLine(int deviceid,int paramid) { IList<OriginalDataInfo> orilist = new List<OriginalDataInfo>(); OriginalData ori = new OriginalData(); IList<ParamInfo> paramdata = ParamDataProxy.GetParams(); //这个方法的作用是通过通过DeviceID和ParamID提取最后的20个数据 orilist = ori.GetTopNDatasByDeviceIDAndParamID(20, deviceid, paramid); int j = orilist.Count; if (j > 0) { string json = "{\"j\":" + j + ",\"rows\":["; double maxitem = 1000;//最多放1000个点在图像上面 int step = j > maxitem ? (int)(maxitem / j) : 1; for (int i = 0; i < orilist.Count; i += step) { json += "{\"time1\":\"" + (Convert.ToDateTime(orilist[i].InsertTime).AddHours(-8) - new DateTime(1970, 1, 1)).TotalMilliseconds + "\",\"price\":\"" + Convert.ToDecimal(orilist[i].ParamValue) + "\"},"; } json = json.TrimEnd(','); json += "]}"; return json; } else { throw new Exception("无数据"); } } }
大体的处理过程:进入页面后首先绘制地图;接下来判断URL中是否包含DeviceID,如果没有,默认为1,否则查询相应Device的数据并放入repeater中;最后提取该设备的数据,绘制曲线图。
相关文章推荐
- icon格式图标下载网站
- ZooKeeper架构
- 基于PetShop的数据可视化网站(二):缓存依赖
- 网站常见的反爬虫和应对方法
- 我的android项目架构
- Pinterest的Feed架构与算法
- 网站反爬虫
- 来自Uber的12条架构重构经验
- 基于PetShop的数据可视化网站(一):基本结构
- Node.js之学习网站
- 大型网站系统架构的演化
- 大型网站的灵魂——性能
- Google Webmasters 网站全新改版,完全支持中文
- 我要带徒弟学架构
- SharePoint 开启网站匿名访问图文详解
- 如何使用ping和tracert命令测试网站访问速度
- (转)VS2012网站发布详细步骤
- 大型网站架构系列:20本技术书籍推荐
- 网站异常了,日志要怎么看?
- 腾讯社区搜索架构演进