highcharts再angularJS中生成单例图表非常容易,但是生成多图表比较困难。为此研究了很久。以下为详细说明。
准备工作:1、在directive中封装一个highcharts的指令。
app.directive('highcharts', function () {
return {
require: '?ngModel',
restrict: 'EA',
link: function (scope, element, attrs, ngModel) {
//选项
var opts = angular.extend({
title: {text: '', enabled: false},
chart: {type: 'column'},
credits: {enabled: false},
//显示打印
exporting: {
enabled: false
},
xAxis: {
labels: {
y: -10, //x轴标签位置
enabled: false
}
},
yAxis: {
allowDecimals: true,
title: {
text: ' '
}
},
series: [],
tooltip: {}
}, scope.$eval(attrs.highcharts));
// var chartrsID = "#" + pagerID;
var opt_data = opts.data;
var new_opts = {
title: opts.title,
chart: opts.chart,
credits: opts.credits,
exporting: opts.exporting,
xAxis: opts.xAxis,
yAxis: opts.yAxis,
series: [],
tooltip: opts.tooltip,
};
var initChart = function () {
new_opts.plotOptions = {
column: {
pointPadding: 0.2,
borderWidth: 0
},
series: {
cursor: 'pointer',
point: {
events: {
click: function (opt) {
if (new_opts.series[opt.point.series.index].url != undefined)
location.href = new_opts.series[opt.point.series.index].url;
}
}
},
animation: false
}
};
$(element).highcharts(new_opts)
};
scope.$watch(opts.data, function (a) {
if (a != undefined && a.length != undefined) {
new_opts.series.splice(0, new_opts.series.length);
for (var i = 0; i < a.length; i++) {
new_opts.series.push(a[i]);
// new_opts.series[i].data = [a[i]];
}
initChart();
}
});
// scope.$watch(opts.data + '.length', function (b) {
// if (b != undefined && b != 0) {
// new_opts.series.splice(0, new_opts.series.length);
// for (var i = 0; i < b; i++) {
// new_opts.series.push(opts.data[i]);
// // new_opts.series[i].data = [a[i]];
// }
// initChart();
// }
// });
}
};
});
2、初始化一个highcharts并在js文件中指向它(
2.1 HTML
<div>highcharts="linechart" style="width:100%;height: 400px;"></div>
2.2 javascript
//数据源
$scope.lineList = [];
//highchair初始化
$scope.linechart = {
data: "lineList",
chart: {type: 'line'}, /*常用的线图为:line,柱状图为:column,横向柱状图为:bar,区域图为:area*/
title: {text: '主机状态', enabled: true},
xAxis: {
categories: []
},
plotOptions: {
boxplot: {
pointPadding: 0
}
},
//提示框位置和显示内容
tooltip: {
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:f}</b></td></tr>',
headerFormat: ""
}
};
)
在以上工作准备完成后分析数据源格式:
首先单例情况下:
我们看到,在初始化highchair数据时,$scope.linechart 中的data 数据源等于一个"lineList"字符串,这个字符串等价于$scope.lineList,这里我们把”lineList“看成一个指针字符,指向了$scope.lineList中的数据,在$scope.linechart中引用”lineList“实际上时引用$scope.lineList中的数据。这是angularJS的机制还是highchair的问题,我没有仔细去找答案。多图例情况的难点就是在这里,如何创建多个指针字符去指向多条数据是关键。接下来先讲单图例,然后是多图例。
单图例:
def host_perform_status(request):
"""单图例数据源"""
line_list = [
# 线图一个字典代表一条线,data里面的必须是数字类型或浮点数类型
{"name": u"线1", "data": [11, 2, 13, 4, 15, 6]},
{"name": u"线2", "data": [7, 16, 5, 14, 3, 12]},
{"name": u"线3", "data": [7, 16, 5, 14, 3, 12]},
]
# 横坐标,一般用字符串列表,列表长度和data保持一致即可
categories = ['a', 'b', 'c', 'd', 'e', 'f']
return render_json({'result': True, 'line_list': line_list, 'categories': categories})
后台数据源比较简单,格式处理成折线图的数据源,返回数据源和横坐标
$scope.lineList = res.line_list;
$scope.linechart.xAxis.categories = res.categories;
讲数据源给到$scope.lineList 横坐标给到$scope.linechart.xAxis.categories
<div highcharts="linechart" style="width:100%;height: 400px;"></div>
前端
以上是单一图例,接下来是多图例。
//查询多条主机的监控信息
def search_host_list(request):
ilter_obj = json.loads(request.body)
//是否有做查询,有则返回满足查询条件的数据,否则返回全部数据(业务)
if filter_obj["appID"] == "":
servers = Servers.objects.filter(is_deleted=False)
else:
servers = Servers.objects.filter(app_id=filter_obj["appID"],is_deleted=False)
//是否有做查询,有则返回满足查询条件的数据,否则返回全部数据(ip,多条ip用回车分割)
if filter_obj["ip"].strip():
ip_list = filter_obj["ip"].split("\n")
servers = servers.filter(ip_address__in=ip_list,is_deleted=False)
return_data = []
//保存多条监控数据格式k:v=={"name": u"线1", "data": [11, 2, 13, 4, 15, 6]}
perform_obj = {}
for i in servers:
key = i.ip_address.replace(".", "_")
result = get_one_server_line_chart_data(i)
//关键1:name的值就是指针字符串
//关键2:每个图表单独的横坐标
one_obj = {
"ip_address": i.ip_address,
"name": 'performObj.ip%s' % key,
"categories": result['categories']
}
//将指针字符和横坐标加入list中
return_data.append(one_obj)
//数据源的key='ip+key',注意,没有performObj的前缀,后在js中会说明处理原因
perform_obj["ip" + key] = result["data"]
return render_json({"result": True, "data": return_data, "perform_obj": perform_obj})
//单条格式处理
def get_one_server_line_chart_data(i):
date_now = datetime.datetime.now() + datetime.timedelta(hours=-1)
server_performs = ServerPerformance.objects.filter(server_id=i.id, when_created__gt=str(date_now).split(".")[0]).order_by("id")
one_obj = [
{"name": "cpu", "data": [i.cpu_usage for i in server_performs]},
{"name": "mem", "data": [i.mem_usage for i in server_performs]},
{"name": "disk", "data": [i.disk_usage for i in server_performs]},
]
return {"categories": [i.when_created for i in server_performs], "data": one_obj}
//筛选条件
$scope.filterObj = {
appID: "",
ip: ""
};
$scope.searchList = function () {
loading.open();
sysService.search_server_perform_list({}, $scope.filterObj, function (res) {
loading.close();
if (res.result) {
$scope.is_search = true;
$scope.serverPerforms = res.data;
$scope.performObj = res.perform_obj;
//对$scope.serverPerforms循环,i是每次循环一次的内容
angular.forEach($scope.serverPerforms, function (i) {
//angular.extend(a,b) b属性给a 并返回a
//在i变量中创建一个chartOptions实例,每个实例都对应着highOption对象。i.chartOptions的值就是具体highOption的值,这里将数据源给到data,i.name等于"performObj.ip192_168_163_130",即指向了数据源$scope.performObjkey等于ip192_168_163_130的数据
i.chartOptions = angular.extend($scope.highOption, {
data: i.name,
xAxis: {categories: i.categories}
});
console.log(i.chartOptions)
})
}
})
};
<div style="margin-top: 5px;width:100%;overflow-y:auto">
<div ng-if="is_search && serverPerforms.length==0" style="text-align: center">
没有查到相关主机
</div>
<div ng-repeat="i in serverPerforms" style="width:50%;float: left;padding:5px;height: 380px;">
<div style="line-height: 30px;font-size: 14px;"><span>{{ i.ip_address }}</span></div>
<div style="width:100%;height: 320px" highcharts="i.chartOptions"></div>
</div>
</div>
以上就是全部的分享。