本文主要是介绍html5 绘制圆饼图,HTML5 Canvas(实战:绘制饼图),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
有了canvas以后,咱们能够很容易地建立一个简单图标,不须要任何插件,不过,有的小伙伴以为它很难,笔者仔细思考一番以后,只能吐嘈一下他们的绘图技能...
因而在开始绘制以前,咱们首先画一下草图~
git
Make It Reusable
为了建立一个能够重用,而且能够灵活地重用的饼图,笔者决定最终的建立饼图方法接收两个参数,分别是要显示的数据data,绘制参数options面试
Data
Data From Server
在实际应用场景中,咱们从后端拿到的每每是诸如几个年份的产量一类的数据,好比(这里,咱们为了简化代码,将颜色也放到了后台返回的数据中):canvas
var data = [
{
data: 10,
color: "red",
label: "2016"
},
{
data: 15,
color: "grey",
label: "2017"
},
{
data: 15,
color: "black",
label: "2018"
}
];
To Process Data
而绘制饼图时, 咱们须要根据比例"分饼", 而且在某些地方显示出实际的数据(好比tooltip),所以咱们须要一个以下的数据处理函数:后端
function calculateData(data) {
if(data instanceof Array) {
var sum = data.reduce(function(a, b) {
return a + b.data;
}, 0);
var map = data.map(function(a) {
return {
label: a.label,
data: a.data,
color: a.color,
portion: a.data/sum
}
});
return map;
}
}
Options
另外,即便咱们能够根据不一样的数据绘制不一样的图表,恐怕也只能知足个别需求,毕竟每一个人的喜爱都不同,咱们须要建立一个能够显示不一样数据,又能够拥有不一样排版、不一样布局的图表,实现上述目标,咱们须要以下参数列表:函数
var options = {
legend: {
font: {
size: 18,
family: 'Arial',
weight: 'bold'
}
},
title: {
text: 'Pie Chart',
font: {
size: 18,
family: 'Arial',
weight: 'bold'
}
},
tooltip: {
template: '
font: {
size: 18,
family: 'Arial',
weight: 'bold'
}
}
}
Canvas
咱们的工具函数不该该能够提早知道用户想要用来绘制图表的canvas,用户可能想在页面中的多个canvas上绘制图表,所以工具函数应该能够接受一个参数,用来肯定绘制图表的canvas,不少开源库都使用id做为识别canvas的标识,笔者认为接收element更好一些,由于不是全部的用户都愿意给canvas添加ID属性, 有的时候,用户想给拥有某一个class属性的全部canvas批量绘图,并根据它们的dataset属性动态的生成数据。
综上,最后咱们的工具函数应该长成下面这个样子:工具
function drawPie(canvas, data, option) {
// To Do
}
Start Coding
Get Context
首先获取绘图上下文,仍要注意先判断是否存在getContext()方法。布局
var canvas = document.getElementById("canvas");
if(canvas.getContext) {
var ctx = canvas.getContext("2d");
}
Generate Options
而后,咱们须要将自定义的参数和默认参数合并在一块儿,组成一个新的完整的参数列表,原则就是没有自定义的都采用默认值。字体
function mergeJSON(source1,source2){
var mergedJSON = JSON.parse(JSON.stringify(source2));
for (var attrname in source1) {
if(mergedJSON.hasOwnProperty(attrname)) {
if ( source1[attrname]!=null && source1[attrname].constructor==Object ) {
mergedJSON[attrname] = mergeJSON(source1[attrname], mergedJSON[attrname]);
}
} else {
mergedJSON[attrname] = source1[attrname];
}
}
return mergedJSON;
}
function generateOptions(givenOptions, defaultOptions) {
return mergeJSON(defaultOptions, givenOptions);
}
Draw Title
把标题绘制在画布顶部的中间,距离页面顶部留有20像素的空隙,而且根据参数,绘制具备特定内容和样式的标题。spa
var width = canvas.width,
height = canvas.height,
op = generateOptions(options, defaultOptions),
title_text = op.title.text,
title_position = {};
ctx.font = op.title.font.weight + " " + op.title.font.size+"px " + op.title.font.family;
title_position .x = (width - title_width)/2;
title_position.y = 20 + op.title.font.size;
title_width = ctx.measureText(title_text).width, title_height = op.title.font.size;
ctx.fillText(title_text, title_position.x, title_position.y);
Radius & Center
笔者决定使饼图距离标题有30像素的空隙,距离左边框和底部分别留有20像素的空隙,所以它的半径和圆心分别是:
var radius = (height - title_height - title_position.y - 20) / 2 ;
var center = {
x: radius + 20,
y: radius + 30 + title_position.y
};
Legend
图例的高设置为图例字体大小的1.2倍,宽设置为图例字体大小的2.5倍,距离饼图40像素的间隙,第一个图例顶部距离页面顶端80像素,文字距离图例5像素,垂直居中,因而图例的大致信息总结以下:
var legend_width = op.legend.font.size * 2.5,
legend_height = op.legend.font.size * 1.2,
legend_posX = center.x * 2 +20,
legend_posY = 80,
legend_textX = legend_posX + legend_width + 5,
legend_textY = legend_posY + op.legend.font.size * 0.9;
Draw Pie & Legends
Border
先给图表加一个边框
ctx.strokeStyle = 'grey';
ctx.lineWidth = 3;
ctx.strokeRect(0, 0, canvas.width, canvas.height);
Pie & Legends
遍历数据绘图。
var data_c = calculateData(data);
var startAngle = 0, endAngle = 0;
for(var i=0, len=data.length; i
endAngle += data_c[i].portion * 2*Math.PI;
ctx.fillStyle = data_c[i].color;
ctx.beginPath();
ctx.moveTo(center.x, center.y);
ctx.arc(center.x, center.y, radius, startAngle, endAngle, false);
ctx.closePath();
ctx.fill();
startAngle = endAngle;
ctx.fillRect(legend_posX, legend_posY + (10 + legend_height) * i, legend_width, legend_height);
ctx.font = 'bold 12px Arial';
var percent = data_c[i].label + ' : ' + (data_c[i].portion*100).toFixed(2) + '%';
ctx.fillText(percent, legend_textX, legend_textY + (10 + legend_height) * i);
}
Let's try it!
咱们的工具函数已经作到一半啦,能够画出一个带有图例的饼图,而且标题和图例文字大小 粗细 字体都可配置,下面试一下灵不灵~
var init = function(){
var data = [
{
data: 10,
color: "red",
label: "2016"
},
{
data: 15,
color: "grey",
label: "2017"
},
{
data: 15,
color: "black",
label: "2018"
}
];
var options = {
title: {
text: 'Production By Year',
font: {
size: 30
}
}
}
drawCircle(data, document.getElementById("drawing"), options);
};
init();
画出来的饼图长这个样子~
下一篇笔者会加上Tooltip的绘制哦,那部分比较复杂,默默地给本身加油~
这篇关于html5 绘制圆饼图,HTML5 Canvas(实战:绘制饼图)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!