• 物联网平台设计心得:图表数据可视化


    本章主要讲解利用Flot图表插件来显示具体的采集数据内容,我们先看成品图片:

    QQ截图20160221205725

    上图中的两个图表,一个代表电压,一个代表电流。鼠标放到图表上的某个点上可以弹出悬浮窗显示当前时间的具体采集信息。

    准备工作

    首先,我们需要用到Flot插件,通过百度,我们就可以找到该项目的具体地址,然后引入到我们项目中:

        <!--Flot Chart Part-->
        <script src="~/Content/front/flot/excanvas.js"></script>
        <script src="~/Content/front/flot/jquery.flot.js"></script>
        <script src="~/Content/front/flot/jquery.flot.time.js"></script>
        <script src="~/Content/front/flot/jquery.flot.resize.js"></script>
        <script src="~/Content/front/flot/jquery.flot.selection.min.js"></script>

    其次,我们的html模板设计如下:

     <!--图表数据-->
        <div class="paramcontainer">
            <div class="panel panel-default">
                <div class="panel-heading">{{selectedMachine.machine_name}}图表数据</div>
                <div class="panel-body" style="padding:5px!important;">
                    <div class="chartcontainer">
                        <div class="row">
                            <history-data ng-repeat="item in HistoryData" options="item"></history-data>
                        </div>
                    </div>
                </div>
            </div>
        </div>

    图表数据绑定及显示

    首先,我们需要设计我们的history-data directive,设计代码如下:

    app.directive('historyData', [function () {
        return {
            restrict: 'AE',
            replace: true,
            scope: { options: "=" },
            link: function (scope, elem, attrs) {
    
                //数据
                var d = eval("[" + scope.options.Param_data + "]");
                //随机线条颜色生成
                var colors = ["#FF0000", "#0062E3", "#FF00CC", "#00CCCC"];
                var index = Math.floor((Math.random() * 4) + 1);
    
                //添加图标鼠标悬浮事件
                var previousPoint = null, previousLabel = null;
    
                elem.on("plothover", function (event, pos, item) {
                    if (item) {
                        debugger;
                        if ((previousLabel != item.series.label) || (previousPoint != item.dataIndex)) {
                            previousPoint = item.dataIndex;
                            previousLabel = item.series.label;
                            $("#tooltip").remove();
    
                            var x = item.datapoint[0];
                            var y = item.datapoint[1];
                            var date = new Date(x);
                            var color = item.series.color;
    
                            showTooltip(item.pageX, item.pageY, color,
                            "<strong>" + item.series.label + "</strong><br>" +
                            (date.getUTCMonth()) + "月" + date.getUTCDate() + "日" + date.getUTCHours() + "时" + date.getMinutes() + "分" +
                            "   " + item.series.label + ": <strong>" + y + "</strong> (" + scope.options.Param_unit + ")");
                        }
                    }
                    else {
                        $("#tooltip").remove();
                        previousPoint = null;
                    }
                });
    
                function showTooltip(x, y, color, contents) {
                    $('<div id="tooltip">' + contents + '</div>').css({
                        position: 'absolute',
                        display: 'none',
                        top: y - 40,
                        left: x - 120,
                        border: '2px solid ' + color,
                        padding: '3px',
                        'font-size': '12px',
                        'color':'white',
                        'border-radius': '5px',
                        'background-color': ''+color+'',
                        'font-family': '宋体,Verdana, Arial, Helvetica, Tahoma, sans-serif',
                        opacity: 0.9
                    }).appendTo("body").fadeIn(200);
                }
               
                //绑定到chart图标
                $.plot(elem, [{ label: scope.options.Param_name, data: d, color: colors[index] }], {
                    xaxis: {
                        mode: "time"
                    },
                    legend: { position: "ne" },
                    series: {
                        lines: { show: true },
                        points: { show: true, fill: false, radius: 2 }
                    },
                    grid: {
                        hoverable: true, //想用tooltip 这里一定要设置hoverable
                        backgroundColor: { colors: ["#fff", "#eee"] },
                        borderWidth: {
                            top: 1,
                            right: 1,
                            bottom: 2,
                            left: 2
                        }
                    }
                });
            },
            template: '<div class="dae-placeholder" style="950px;height:200px;margin-left:20px;"></div>'
        };
    }]);

    从这个模板中,我们可以看到,数据部分来源于<history-data ng-repeat="item in HistoryData" options="item"></history-data>中的options选项,然后通过ng-repeat来绑定多个图表(如果有多个图表数据传来的话)。

    最后是我们的HistoryData数据来源:

        var historyDataList = function (machineId,starttime,endtime) {
            return $http({
                method: 'POST',
                url: '/Machine/GetHistoryCollectorDataByMachine?machineId=' + machineId + "&paramId=&starttime=" + starttime + "&endtime=" + endtime
            });
        }

    后台拼接如下:

      [HttpPost]
            public JsonResult GetHistoryCollectorDataByMachine(string machineId,string paramId,string starttime,string endtime)
            {
                DateTime start,end;
                
                if(DateTime.TryParse(starttime,out start))
                    starttime= start.ToString("yyyy-MM-dd")+" 00:00:00";
    
                if (DateTime.TryParse(endtime, out end))
                    endtime = end.ToString("yyyy-MM-dd") + " 23:59:59";
    
                //首先获取采集设备的参数列表
                var whereSQL = " where data.machine_id='" + machineId + "' ";
                if (!string.IsNullOrEmpty(paramId))
                    whereSQL += "  and param_id = '" + paramId.ToString() + "' ";
    
                var groupSQL = " group by data.route_id,data.param_id,data.machine_id,setting.settingname,setting.settingvalue4 ";
    
                var mainSQL = @"select machine_id
                                   ,route_id
                                   ,param_id
                                   ,setting.settingname
                                   ,setting.settingvalue4
                              from ds_collector_data data
                              join edu_base_setting setting 
                              on data.param_id = setting.settingvalue1 ";
    
                var allSQL = mainSQL + whereSQL + groupSQL;
    
                var groupResultList = fuNongContext.SqlQuery<CollectorGroup>(allSQL).Cast<CollectorGroup>().ToList();
    
                var chartDataList = new List<CollectorChartFmt>();
                var plainDataList = new List<CollectorChartFmt>();
    
                //遍历参数列表取数据
                if (groupResultList != null)
                {
                    //遍历采集器
                    groupResultList.ForEach(item =>
                    {
                        var historySelectSQL = @" select  data.data_value,data.data_time from ds_collector_data data ";
                        var historyWheresSQL = @" where data.machine_id='" + item.machine_id + "' and data.route_id=" + item.route_id + " and data.param_id='" + item.param_id + "' ";
                        var historyOrdersSQL = @" order by data.data_time desc ";
    
                        var historyFilterSQL = string.Empty;
    
                        if(!string.IsNullOrEmpty(starttime) && !string.IsNullOrEmpty(endtime))
                        {
                            historyFilterSQL = @" and (data.data_time >= '" + starttime + "' and data.data_time <='" + endtime + "') ";
                        }
                        if(string.IsNullOrEmpty(starttime) && string.IsNullOrEmpty(endtime))
                        {
                            historySelectSQL = @" select top 100 data.data_value,data.data_time from ds_collector_data data ";
                        }
    
                        var historyMainSQL = historySelectSQL + historyWheresSQL + historyFilterSQL + historyOrdersSQL;
    
                        var historyDataList = fuNongContext.SqlQuery<CollectorChart>(historyMainSQL).Cast<CollectorChart>().ToList();
                        if (historyDataList == null)
                        {
                            chartDataList.Add(new CollectorChartFmt() { Param_name = "无", Param_unit = "无", Param_data = "[]"});
                        }
                        else
                        {
                            var container = new List<string>();
                            historyDataList.ForEach(x =>
                            {
                                var time = "Date.UTC(" + x.data_time.ToString("yyyy,MM,dd,HH,mm,ss") + ")";
                                var data = x.data_value;
                                var val = "[" + time + "," + float.Parse(data) + "]";
                                container.Add(val);
                                plainDataList.Add(new CollectorChartFmt() { Param_name = item.settingname, Param_unit = item.settingvalue4, Param_data = data, Param_time = x.data_time.ToString("yyyy-MM-dd HH:mm:ss") });
                            });
                            chartDataList.Add(new CollectorChartFmt() { Param_name = item.settingname, Param_unit = item.settingvalue4, Param_data = string.Join(",", container) });
                        }
    
                    });
                }
    
                return Json(new { success = true, data = chartDataList, list = plainDataList }, JsonRequestBehavior.AllowGet);
    
            }

    也就是说,后台传过来的数据只要保持类似如下图的数据结构即可:

    QQ截图20160221210822

  • 相关阅读:
    怎么说???
    再给自己一点鼓励
    还是不要看新闻的好
    系统架构师
    朋友
    未来的路
    I now have a dream
    纪念死去的手机
    全局规划
    终于要上战场了!
  • 原文地址:https://www.cnblogs.com/scy251147/p/5205577.html
Copyright © 2020-2023  润新知