六、变换
现在我们来说一下在canvas上绘制图像的另一种方式——使用变换。接下来的代码显示结果和上面一样。只是绘制对角线的代码不同。这个示例可能会让人感觉使用变换增加了不必要的复杂性。但是实际上变换是实现复杂canvas操作的最好方式。在后面的示例中将会看到,我们使用了大量的变换,而这对数据Canvas的复杂功能至关重要。
我们可以把变换当成是介于开发人员发出的指令和canvas显示结果之间的一个修正层。不管开发中是否使用变换,修正层始终都是存在的。
修正——在绘制系统中的说法是变换——在应用的时候可以被顺序应用、组合或者随意修改。每个绘制操作的结果显示在canvas上之前都要经过修正层去做修正。虽然这么做增加了额外的复杂性,但却为绘制系统添加了更为强大的功能,可以像目前主流图像编辑工具那样支持实时的图像处理,所以API中这部分内容的复杂性是必要的。
translate函数
//获取canvas对象 var canvas = document.getElementById("square"); //获取context对象 var context = canvas.getContext("2d"); //保存当前绘图状态 context.save(); //向右下方移动绘图上下文 context.translate(70,140); //以原点为起点,绘制与前面相同的线段 context.beginPath(); context.moveTo(0,0); context.lineTo(70,-70); context.stroke(); //恢复原有的绘图状态 context.restore(); |
解析:
- 通过id获取canvas对象
- 调用canvas.getContext(“2d”)获取上下文对象
- 保存尚未修改的context
- 调用translate()函数。通过这个操作,当平移行为发生的时候,我们提供的变换坐标会被添加到结果坐标上,结果就是将对角线移动到了新的位置上。
- 应用平移后就可以使用普通的绘制操作来画对角线了。
- 在这条线勾画出来以后,调用stroke将其显示在canvas上
- 恢复context值原始专题,这样后续的canvas操作就不会被刚才的平移操作影响。
执行结果:
虽然新绘制的对角线看着和前面的一模一样,但是这次绘制已经使用了强大的变换功能。下边我们还要来体会变换的强大之处。
七、路径
Canvas中的路径代表你希望呈现的任何形状。上边的对角线就是一条路径,beginPath就说明是要开始绘制路径了。实际上,路径可以要多复杂有多复杂:多条线、曲线段,甚至是子路径。如果想要在canvas中绘制任意形状那么我们需要来关注一下路径的API。
一般的,开始绘制图形之前,第一个就要调用beginPath。这和函数不带任何参数,它用来通知canvas将要开始绘制一个新的图形了。对于canvas来说,beginPath函数的最大用处是canvas需要根据此来计算图形的内部和外部的范围,以便完成后续的描边和填充。
路径会跟踪当前坐标,默认值是原点。Canvas本身也跟踪当前坐标,不过可以通过绘制代码来修改。
调用beginPath后,就可以用context的各种方法来绘制想要的形状了。到目前为止,我们已经用到了几个简单的context路径函数。
- moveTo(x,y):不绘制,只是将当前位置移动到新的目标坐标(x,y)。
- lineTo(x,y):不仅将当前位置移动到新的目标坐标(x,y),而且在两个坐标之间画一条直线。
下一个特殊的路径函数叫做closePath。这个函数的行为同lineTo很像,唯一的差别在于closePath会将路径的起始坐标自动作为目标坐标。closePath还会通知canvas当前绘制的图像已经闭合或者形成了完全封闭的区域,自对将来的填充和描边都非常有用。
此时可以在已有的路径中继续创建其他子路径,或者随时调用beginPath重新绘制新路径并完全清除之前所有的路径。
下边我们尝试着绘制一个松树的路径(注意这里画布调到了300 X 300):
window.onload = function(){ var canvas = document.getElementById("square");
var context = canvas.getContext("2d");
context.save(); context.translate(130,250);
//开始绘制 //绘制树冠 context.beginPath();
context.moveTo(-25,-50); context.lineTo(-10,-80); context.lineTo(-20,-80); context.lineTo(-5,-110); context.lineTo(-15,-110);
//树的顶点 context.lineTo(0,-140);
context.lineTo(15,-110); context.lineTo(5,-110); context.lineTo(20,-80); context.lineTo(10,-80); context.lineTo(25,-50);
//连接起点,闭合路径 context.closePath();
//绘制当前路径 context.stroke(); context.restore(); }; |
上边的代码实际上使用的依然是前面用过的移动和画线的命令,只不过调用的次数多了一些。这几条线表现出了一棵松树的轮廓,最后我们闭合了路径。
本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源。