chartjs是一款非常好用的数据可视化工具,对比了echarts、highcharts、c3、flot、amchart等各种工具后,现在我的画图表工具基本90%都是用chartjs来搞定。
画面效果、动态效果都很精致,清爽简洁,基本满足了一般数据展示的需要,现在ppt都懒得做了。
用php结合chartjs,效果棒棒。
上几张图,show一下。
不过问题也不少,数据不能在图上显示,这个很头疼,在网上找到的解决方法也只有柱状图的,并没有圆环图、曲线图,于是上chartjs的官网上,下载了未压缩版的chart.js文件,终于找到了解决办法,效果如下。
chartjs
就是用canvas
ctx
画图,不嫌麻烦就可以为所欲为了。
柱状图中,关键在在option
中的animation
,如下:
options: {
animation: {
duration: 1,
onComplete: function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillStyle = '#006080';
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(arc, index) {
var data = dataset.data[index];
var ct=Math.round(arc._model.width*0.35);
if(ct<12){ct=12;}
ctx.font=ct+'px Arial';
ctx.fillText(data, arc._model.x, data>=0?arc._model.y :arc._model.y+15);
});
});
}
},
doughnut圆环图,我是这么写的。
options: {
animation: {
duration: 1,
onComplete: function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
var i, len;
var x = 0;
var y = 0;
var count = 0;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textBaseline = 'bottom';
// var total = this.data.total;
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
var arc = meta.data[i];
var objLt10=0;//object less than 5%
var total =eval(dataset.data.join("+"));
meta.data.forEach(function(arc, index) {
var data = dataset.data[index];
var textshift=0;
if(data!=0){
var chartCenterX = arc._model.x;
var chartCenterY = arc._model.y;
var arcCenter = calc(arc._model.startAngle, arc._model.endAngle, arc._model.outerRadius*1.1, arc._model.innerRadius, chartCenterX, chartCenterY);
if(arc._model.circumference<0.314){
ctx.textBaseline = 'bottom';
objLt10++;
ctx.font="14px Arial";
ctx.fillStyle=arc._model.backgroundColor;
if(objLt10<=10) {
ctx.textAlign = 'left';
blockx=10;
cx=60;
cy=chartCenterY+arc._model.outerRadius+20-objLt10*25;
text='██ '+Math.round(data*100/total)+'%' ;
}else{
ctx.textAlign = 'right';
cx=arc._model.x*2-60;
blockx=arc._model.x*2-10;
cy=chartCenterY+arc._model.outerRadius+20-(objLt10-10)*25;
}
ctx.fillText(text, blockx,cy);
ctx.fillStyle='#808080';
ctx.fillText(arc._model.label+' '+data, cx,cy);
}else if(arc._model.circumference<0.628){
var textStart= calc(arc._model.startAngle, arc._model.endAngle, arc._model.outerRadius*1.1, arc._model.outerRadius, chartCenterX, chartCenterY);
var lineStart= calc(arc._model.startAngle, arc._model.endAngle, arc._model.outerRadius, arc._model.outerRadius*0.8, chartCenterX, chartCenterY);
var textCenterX = textStart.x;
var textCenterY = textStart.y;
if(textCenterY>arc._model.y+arc._model.outerRadius-20)
{
textCenterY=arc._model.y+arc._model.outerRadius-20;
textCenterX=textStart.x>arcCenter.x?textStart.x+50+textshift:textStart.x-50-textshift;
textshift=50;
}else if(textCenterYarcCenter.x?textStart.x+50+textshift:textStart.x-50-textshift;
textshift=50;
}else{
textCenterX=textStart.x>arcCenter.x?textCenterX+textshift:textCenterX-textshift;
textshift=0;
};
ctx.strokeStyle=arc._model.backgroundColor;
ctx.beginPath();
ctx.moveTo(lineStart.x,lineStart.y);
ctx.lineTo(textCenterX,textCenterY>chartCenterY?textCenterY+13:textCenterY);
ctx.lineTo(textCenterX+(textStart.x>arcCenter.x?50:-50),textCenterY>chartCenterY?textCenterY+13:textCenterY);
ctx.stroke();
ctx.font="16px Arial";
ctx.textAlign = textStart.x>arcCenter.x?'left':'right';
ctx.textBaseline = 'bottom';
ctx.fillStyle="#006080";
ctx.fillText( arc._model.label+' '+data,
textCenterX, textCenterY>chartCenterY?textCenterY+13:textCenterY);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle=changeColor(arc._model.backgroundColor);
ctx.fillText(Math.round(data*100/total)+'%',
arcCenter.x,arcCenter.y);
}else if(arc._model.circumference>=0.628){
var arcCenterX = arcCenter.x;
var arcCenterY = arcCenter.y;
ctx.font="20px Arial";
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillStyle=changeColor(arc._model.backgroundColor);
ctx.fillText(Math.round(data*100/total)+'%', arcCenterX, arcCenterY=chartCenterY?arcCenterY+15:arcCenterY-5);
}
}
});
});
}
},
为了提高显示效果,针对对于5%、5% ~ 10%之间、超过10%分开处理。达到自己觉得还满意的结果。
ps:还得带一个外挂,计算圆环的中心坐标。
function calc(startAngle, endAngle, outerRadius, innerRadius ,x,y ) {
var centreAngle = startAngle + ((endAngle - startAngle) / 2);
var rangeFromCentre = (outerRadius - innerRadius) / 2 + innerRadius;
return {
x: x + (Math.cos(centreAngle) * rangeFromCentre),
y: y + (Math.sin(centreAngle) * rangeFromCentre)
}
};
为了让随机得到的颜色上面的字体显示效果更好,设置了一个反差色的函数changeColor(),这个在下一篇文章里面分享吧。