HTML5 canvas最流行的应用之一是绘制图表。我们将用一个很简单的例子,讲述如何在画布上绘制图表。明白这些基本概念后再进一步深化,就可以使我们的图形功能更灵活。
下面是我们简单绘制图表的步骤:
- 创建2D画布context对象
- 绘制X轴
- 绘制Y轴
- 基于数据绘制路径
我们需要理解如何在画布上元素绘制多个点。在X轴从左边0开始,向右移值增加,y轴从0开始的顶部,向向下移值增加。如下图:
让我们将画布放置在页面上。
<canvas id="canvas" width="180" height="105"> Your browser does not support the canvas element. </canvas>
要在画布上绘图,我们需要使用JavaScript引用canvas元素。我们用init()函数实现这一功能并在初始化时调用它。
function init() { canvas = document.getElementById("canvas"); if(canvas.getContext) { ctx = canvas.getContext("2d"); draw(); } }
首先,我们通过canvas的id搜索DOM元素得到画布元素,然后新建了一个画布context对象,该对象可以在JavaScript内部完成绘制工作。 context对象包含在画布上绘图的基本方法,比如arc(), lineto() 和stroke()。
然后调用draw()函数来绘制图表。
function draw() { clear(); drawaxes(); plotdata(); }
我们调用clear()函数,该函数使用clearRect()方法来清除一个与画布同样大小矩形。清除的矩形的两个对角设置为(0,0)和(宽,高)。宽度和高度与画布上的宽度高度相同。你可以很容易部分清除画布,但我们想要的是清空画布。
function clear() { ctx.clearRect(0, 0, WIDTH, HEIGHT); }
接下来,使用drawaxes()函数在画布左侧和底部绘制X轴和Y轴。
function drawaxes(){ ctx.strokeStyle = "black"; ctx.beginPath(); /* y axis along the left edge of the canvas*/ ctx.moveTo(0,0); ctx.lineTo(0,105); ctx.stroke(); /* x axis along the bottom edge of the canvas*/ ctx.moveTo(0,105); ctx.lineTo(180,105); ctx.stroke(); }
context对象的strokestyle属性设置成想要的笔触颜色,在使用stroke()方法绘制路径时会用到它。
ctx.strokeStyle = "black";
然后我们从新建的路径开始绘制。
ctx.beginPath();
现在,我们利用创建的新路径,使用stroke方法绘制Y轴。
/* y axis along the left edge of the canvas*/ ctx.moveTo(0,0); ctx.lineTo(0,105); ctx.stroke();
同样的方法绘制X轴。
/* x axis along the bottom edge of the canvas*/ ctx.moveTo(0,105); ctx.lineTo(180,105); ctx.stroke();
下一步,在draw()方法中调用plotdata()方法。
function plotdata() { ctx.strokeStyle = "rgb(0,0,165)"; ctx.lineWidth = 1; ctx.beginPath(); ctx.lineJoin = "miter"; ctx.moveTo(0, HEIGHT - (temps[0])); j = 1; for (var i in temps) { ctx.lineTo(j * 30, HEIGHT - (temps[j])); ctx.stroke(); j++; } }
同样,设置context对象的strokestyle属性,从新建路径开始绘制。
ctx.strokeStyle = "black"; ctx.beginPath();
移至坐标原点。从顶部至底部Y轴值下降,但打算我们顶端表示数据的最小值,底端表示数据的最大值,因此我们使用如下公式:
ctx.moveTo(0,HEIGHT-(temps[0]));
这个公式有效地反转温度值,因此距离底部80像素,而不是距离顶部80像素。现在,我们遍历其它的温度值并在每个相邻值之间画一条线。
j = 1; for (var i in temps) { ctx.lineTo(j * 30, HEIGHT - (temps[j])); ctx.stroke(); j++; }
我们使用j * 30,每个数据点间距为30像素,而不是7像素,这样才有足够的空间。
点击此处查看本实例的效果。