先说说这个demo的灵感来源。
我以前有一同事,技术在我心目中算是非常厉害的那种,我这一年多来的技术提高基本上完全靠他所赐,再次对他表示深深的感谢啊!
一次偶然的机会,让我见识了他的前端博客,其中里边有一个demo给我的印象特别深,好像名字叫做”svg burndown”.
顾名思义,他的这个demo是用svg做的,我觉得挺有意思,于是下定决心自己做一个,svg已经被他用过了,再用就没意思了。
剩下的也就只有html5的canvas可以考虑了,虽然自己的canvas功底不算很强,但还是决定大胆尝试一番。
燃尽图是现在团队敏捷开发非常重要的考量工具,对于团队的分工、进度把控、成员协作等方面起到非常重要的作用。
燃尽图主要分为以下几个部分:
1、坐标轴
主要分为x轴和y轴,其中x轴表示时间,y轴表示剩余任务量,y轴为0时表示任务全部完成。
drawCoordinate: function() {
sContext.beginPath();
sContext.moveTo(xSpace, 0);
sContext.lineTo(xSpace, config.height - ySpace);
sContext.lineTo(config.width, config.height - ySpace);
sContext.lineWidth = 3;
sContext.strokeStyle = 'rgba(0,0,0,0.5)';
sContext.stroke();
sContext.closePath();
},
drawScaleX: function() {
sContext.beginPath();
sContext.moveTo(xSpace, config.height);
var len = timeList.length;
sContext.textAlign = 'center';
for(var i = 0; i < len; i++) {
var date = timeList[i];
var show = date[2] +'/'+ (parseInt(date[1])+1);
var x = config.width/(len+1)*i + xSpace;
if(i > 0) {
sContext.moveTo(x, 0);
sContext.lineTo(x, config.height - ySpace);
maxX = [x, config.height - ySpace];
}
scaleX[i] = x;
sContext.fillText(show, x, config.height - 5);
}
sContext.lineWidth = 1;
sContext.strokeStyle = '#eeeeee';
sContext.stroke();
sContext.closePath();
},
drawScaleY: function() {
var num = 0;
var max = config.taskMax;
var step = config.taskStep;
var len = max/step;
var pLen = parseInt(max/step);
len = len === pLen ? pLen+1 : pLen+2;
sContext.beginPath();
sContext.moveTo(xSpace, config.height);
sContext.textAlign = 'right';
sContext.textBaseline = 'middle';
for(var i = 0; i < len; i++) {
var y = config.height - ySpace - config.height/len*i;
if(i > 0) {
if(i === len - 1) {
y = ySpace;
num = config.taskMax;
}
sContext.moveTo(config.width, y);
sContext.lineTo(xSpace, y);
maxY = [xSpace, y];
}
sContext.fillText(num+'', xSpace, y);
num += step;
}
sContext.strokeStyle = '#eeeeee';
sContext.stroke();
sContext.closePath();
},
2、参考线
参考线是指标准的项目燃尽线路图,当然,在具体项目中,几乎不可能完全按照参考线的路径一直往下走,一般都是在参考线上下徘徊才算正常。
drawRefLine: function() {
sContext.beginPath();
sContext.moveTo(maxY[0], maxY[1]);
sContext.lineTo(maxX[0], maxX[1]);
sContext.lineWidth = 3;
sContext.strokeStyle = 'rgba(255,255,0,0.5)';
sContext.stroke();
sContext.closePath();
},
3、燃尽线路
燃尽图最重要的便是燃尽线路,每当到了一个时间点,就应该更新燃尽图,具体的操作便是添加一个坐标,许多个坐标连成线变成了燃尽线路。当最后一个时间点的任务量剩余不为0时,表示任务没有完成,同志人须努力啊。
drawBurnLine: function(task) {
task && !this.isSameDate(task) && taskList.push(task);
taskList = taskList.sort();
lContext.clearRect(0, 0, config.width, config.height);
lContext.beginPath();
lContext.moveTo(maxY[0], maxY[1]);
for(var i = 0; i < taskList.length; i++) {
var x = taskList[i][0];
var y = taskList[i][1];
for(var j = 0; j < scaleX.length; j++) {
if(x.join('') === timeList[j].join('')) {
var xx = scaleX[j];
var yy = y > 0 ? (1 - y/config.taskMax)*(config.height - ySpace) : config.height - ySpace;
lContext.lineTo(xx, yy);
lContext.arc(xx, yy, 3, 0, Math.PI*2, true);
break;
}
}
}
lContext.lineWidth = 3;
lContext.strokeStyle = 'rgba(0,0,255,0.5)';
lContext.stroke();
lContext.closePath();
},
以上便是canvas燃尽图的大致实现原理,肯定还有诸多瑕疵,希望看完后能给个评价,自当虚心接受。
demo演示效果地址:http://xiechengxiong.com/221.html
欢迎光临我的前端博客: http://xiechengxiong.com/