hightcharts使用的范围应该很广了,但是因为他的渲染方式是svg,当数据量达到成千上万条的时候,那么问题就来了,浏览器会卡死,渲染不出来。这个问题官方已经给了解决实例。但是很少被人注意到,我遇到这个问题的时候,网上查了半天才发现。 下面实例总结一下,先说一下Highcharts、Highstock的区别:
Highcharts的数据量理论是万级,默认是1000,可以通过 turboThreshold 来指定。 Highstock的数据量可以达到十万甚至是百万级,通过异步加载等优化手段可以轻松胜任百万数据。
html代码
<html>
<head>
<meta http-equiv=Content-Type content=text/html; charset=utf-8>
<meta name=viewport content=width=device-width, initial-scale=1>
<title>DPUv2 Profiler</title>
<script src=./jquery-3.1.1.min.js></script>
<script src=./highstock.js></script>
<script src=./modules/xrange.js></script>
<script src=./modules/exporting.js></script>
<style type=text/css>
#container {
width: 100%;
height: 600px;
margin: 1em auto;
}
</style>
</head>
<body>
<div id=container></div>
</body>
</html>
js部分
<pre class="line-numbers" data-start="1" prism-highlight="">```null
var chartData = []//所有数据
var options = {
chart: {
type: 'xrange',
renderTo: container,
zoomType: 'x'
},
title: {
text: 'DPUv2 Profiler'
},
yAxis: {
title: {
text: ''
},
categories: ['LOAD', 'SAVE', 'CONV', 'MISC'],
reversed: true
},
xAxis : {
events : {
afterSetExtremes : afterSetExtremes
}
},
navigator: {
adaptToUpdatedData: false,
enabled: true,
height: 120,
xAxis: {
visible: false
},
yAxis: {
reversed: true,
visible: false
},
series: {
type: 'xrange',
dataGrouping: {
enabled: true
}
}
},
keyboardNavigation: {
mode: 'normal'
},
scrollbar: {
enabled: true
},
rangeSelector: {
enabled: false
},
tooltip:{
headerFormat: '<small>partialFill</small>: ',
pointFormatter: function(){
let html = '<b>' + this.partialFill + '</b><br/>'
html += currentLine: +this.sort
for(key in this.info){
html += '<br/><p><span>' + key + ': </span>' +
'<span style=text-align: right><b>' + this.info[key] + '</b></span></p><br/>'
}
return html
},
valueDecimals: 2
},
series: [{
turboThreshold: 0,
name: '',
borderColor: '#E0E0E0',
pointWidth: 30,
pointPadding: 0,
showInLegend: false,
allowPointSelect: true,
showInNavigator: true,
data: [{}],
dataLabels: {
enabled: false
},
states: {
select: {
color: '#888888'
}
}
}]
}
function dataHandle(data){
var dest = []
data.forEach((item,index)=>{
var color
switch(item.name) {
case 'LOAD':
color = '#90EE90'
break
case 'SAVE':
color = '#FF69B4'
break
case 'END':
color = '#000000'
break
case 'CONVINIT':
color = '#BA55D3'
break
case 'CONV':
color = '#6495ED'
break
case 'POOL':
color = '#FFD700'
break
case 'ELEWINIT':
color = '#FFA07A'
break
case 'ELEW':
color = '#FF6347'
break
default:
color = #999999
}
dest.push({
x: parseInt(item.x),
x2: parseInt(item.x2),
y: parseInt(item.y),
name: item.name,
color: color,
info: item.info,
partialFill: 1 - parseFloat(item.efficiency),
dpd: item.dpd,
id: index + 1,
sort:item.sort
})
})
return dest
}
function afterSetExtremes(e) {
var chart = $('#container').highcharts()
chart.showLoading('Loading data from server...')
var dest = []
chartData.forEach((item,index)=>{
if((item.x2 >= (e.min)) && (item.x <= e.max)){
dest.push(item)
}
})
console.log(dest)
var data = dataHandle(dest)
chart.series[0].setData(data)
chart.hideLoading()
}
function GetQueryString(name) {
var reg = new RegExp((^|&)+ name +=([^&]*)(&|$));
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
}
function JsonCount(jsonArr){
var JsonOBj = []
var tempArr = []//记录分类
JsonOBj.all = jsonArr.length
jsonArr.forEach((item,index)=>{
jsonArr[index].sort = index + 1 //给原始数据加个序号
if(tempArr.indexOf(item.name) < 0){
//还没这项
JsonOBj[item.name] = 1
tempArr.push(item.name)
}else{
JsonOBj[item.name] ++
}
})
return JsonOBj
}
function renderCount(countData){
let html =
console.log(countData)
for(var key in countData){
html += <li><b>+key+: </b>+countData[key]+</span></li>
}
$(.info_list).html(html)
}
$(function(){
var filename = GetQueryString('file')
$.getJSON('/gantt/'+filename, function(data) {
chartData = data
var countData = JsonCount(chartData)
renderCount(countData)
var loadData = dataHandle(data.slice(0,200))
options.series[0].data = loadData
new Highcharts.Chart(options)
})
})
根据官网demo改造的,原文链接https://www.hcharts.cn/demo/highstock/lazy-loading其中dataHandle
是把我们的json数据处理成highcharts期望渲染的数据结构。 核心原理就是首次渲染的时候,先渲染了数据的前200条。区间选取的时候会触发afterSetExtreme()函数,我们根据e.min&&e.max过滤我们的数据然后重新渲染。