canvas是HTML5中十分有意思的应用。利用canvas我们可以运用基本的数学知识就能绘画出很多有意思的图案。
像目前比较流行的数据可视化插件,Echarts,HighCharts等都是利用的canvas来进行描绘的。
前段时间碰到一个需求,我需要做一个有缺口的圆形图表,来表达一种百分比占有量。类似于仪表盘的效果。
每个用户的占用比例是不同的,所以这个数据可视化就必须是能够动态的改变的。
于是,canvas成为了一个不错的选择。
、
代码实现如下:
var Arccanvas = function(Total, SY, eleID) {
/**
* total:总数
* remaind:剩余数
* captionText:图说明
* x:剩余数占总数的百分比
* sin:Math.sin函数
* cos:Math.cos函数
* PI:Math.PI
* R_x,R_y:画圆的坐标,canvas元素的中心点
*
*/
var eleDiv = document.getElementById("" + eleID + "");
eleDiv.innerHTML = "";
var ele = ""
eleDiv.innerHTML = ele;
var canvas = document.getElementById("mycanvas"),
total = Total ? Total : 100,
Sy = SY ? (SY >= 0 && SY <= Total ? SY : Total) : 0,
x = Sy / total * 10,
captionText = "有效套餐",
sin = Math.sin,
cos = Math.cos,
PI = Math.PI,
R_x = canvas.width / 2,
R_y = canvas.height / 2,
cv = canvas.getContext("2d");
// cv.fillStyle = "#ff0";
// cv.fillRect(0, 0, canvas.width, canvas.height);
cv.textBaseline = 'middle';
cv.textAlign = 'center';
/*******************************************************
* 先画外面的大圆,canvas起点和终点都是顺时针来找角度的。
* 所以选好角度,选择逆时针来画就能画出效果
******************************************************/
cv.lineWidth = 14;
cv.strokeStyle = "#999999";
cv.beginPath();
cv.arc(R_x, R_y, 150, PI / 3, PI * 4 / 6, true);
cv.stroke();
/********************************************************
* 画大圆上面的百分比占有量的小圆。
* 将0%-100%我设定的数值区间为 0-10;所以,求得百分比后要*10;
* 根据外面大圆的特性,通过构造函数模型来生成。
* 这个模型是分段函数。
* y=πx/6+2π/3 (8=>x>=0);
* y=π(x-8)/6; (10=>x>8);
* 通过计算终点角度来实现百分比覆盖。
********************************************************/
cv.lineWidth = 14;
cv.beginPath();
cv.strokeStyle = "#39f";
if (x >= 0 && x <= 8) {
cv.arc(R_x, R_y, 150, PI * 2 / 3, PI * x / 6 + 2 * PI / 3, false);
} else if (x > 8 && x <= 10) {
cv.arc(R_x, R_y, 150, PI * 2 / 3, PI * (x - 8) / 6, false);
}
cv.stroke();
cv.closePath();
/************************************************************
* 绘制圆圈内侧的百分比文字
* 通过三角函数来实现文字坐标的平移
* x=-R*sin((π*i)/6+π/6);
* y=R*cos((π*i)/6+π/6);
************************************************************/
cv.font = '12px 宋体';
cv.lineWidth = 1;
for (var i = 0; i <= 10; i++) {
//cv.strokeStyle = '#f00';
var text = (i * 10) + '%';
cv.save();
cv.translate(-130 * sin(PI * i / 6 + PI / 6), 130 * cos(PI * i / 6 + PI / 6));
cv.strokeText(text, R_x, R_y);
cv.restore();
}
/************************************************************
* 绘制内层有色填充圆 *
************************************************************/
cv.beginPath();
cv.arc(R_x, R_y, 100, 0, 360, false);
cv.fillStyle = "#d8e2ec";
cv.fill();
cv.closePath();
cv.save();
/************************************************************
* 绘制套餐剩余数目与总数目的比值表达式 *
************************************************************/
cv.beginPath();
cv.font = '16px 宋体';
cv.moveTo(R_x, R_y);
cv.translate(0, 0)
cv.strokeText(Sy + "/" + total, R_x, R_y);
cv.closePath();
/***************************************************************
* 绘制图表反应的主题信息 *
***************************************************************/
cv.beginPath();
cv.font = '16px 宋体';
cv.moveTo(R_x, R_y);
cv.translate(0, 20)
cv.strokeText(captionText, R_x, R_y);
cv.closePath();
}
/**调用*/
Arccanvas();