在前端最令人兴奋的技术莫过于Canvas技术。它可以制作出更加绚丽的效果,甚至完全可以胜任游戏开发。最近我也在学习Canvas相关的技术,总是想拿出来跟大家一起分享分享,由于这块技术比较庞大,所以我就分章节一章一章地跟大家分享。这几章节中我们并不涉及webGL相关的知识,感兴趣的可以自己玩一玩。
我们的全部代码可以在这个网址查看:https://github.com/KaiOrange/canvas-demo。
快速上手
在HTML5中,涌现了很多的新技术,其中最令人兴奋的就是Canvas。我就不卖关子了,直接快速使用吧。首先我们有这样的HTML代码:
1 |
|
这个是我们的模板,如果你想好好学习的话,建议你也创建一个index.html
文件,并且把代码敲一下。此时我们看到的效果是这个样子的:
canvas标签默认的样式是大小为300 * 150
像素、没有背景色
的行内替换元素,类似于img标签。我们这里为了看上去更加方便给了一个背景元素。
要使用canvas进行绘图,需要使用JavaScript去控制它,现在我们就在script标签中添加JavaScript代码来绘制一条直线:
1 | // 1. 获取canvas元素 |
通过上面几行代码我们知道canvas绘图的时候无非就是三个步骤:
- 获取canvas元素
- 获取上下文对象
- 绘制图片
第一步获取canvas元素其实就是DOM操作,获取到的canvas元素也是DOM元素,DOM元素就有大量的DOM相关的属性和方法了,可以使用console.table(canvas);
打印一下。canvas中最重要的属性和方法莫过于这四个:
属性或方法 | 含义 |
---|---|
width | 长度 |
height | 宽度 |
getContext(‘2d’) | 获取2D上下文,如果是WebGL可以传webgl |
toDataURL() | 获取转换的位图字符串(后面会简绍) |
第二步中传递的是2d
,这样会返回一个绘制2D图形的上下文,也就是context
对象。因为canvas是画布的意思,有人也把上下文对象成为画笔。如果要绘制3D图像怎么办?可以传一个webgl
来获取WebGL的上下文,这样就可以绘制3D效果了(WebGL是基于OpenGL,是已存在的一套技术,所以并没有使用3D来获取3D的上下文,有可能以后开发出性能更加优越的3D绘制系统的话可能会取代WebGL,当然短期内是不会的,毕竟WebGL加上部分库用起来也很方便,性能也挺不错的)。
最重要的第三步,canvas提供了大量的API供我们绘制图片,我们下面几个章节会重点简绍。
最后需要注意2点:
- 计算机中除了WebGL等少数坐标系的y轴是向上的,其他的都是向下的,我们的2d上下文的y轴就是向下的。
- 设置canvas大小的时候使用HTML中的属性设置,而不要使用CSS设置,如果使用CSS设置后会缩放。
对于第二条特别重要,我们试着修改CSS:
1 | #canvas{ |
可以看到线段仍然是居中的,而且明显粗了,这是缩放导致的。
使用HTML控制如下:
1 | <canvas id="canvas" width="150" height="300"></canvas> |
绘制2条线段
绘制线段用到2个API:
1 | // 将画笔移动到(x1, y1)的坐标 |
通过上述2步以后其实并没有画线,通过上面可以看到还需要调用context.stroke();
,这一点一定要记住。为什么要多此一步呢?一方面是因为一次性统一绘制会减少内存的开销,另一个原因是因为canvas不仅仅支持描边(stroke)还支持填充(fill),后面马上就会遇到了。
那如果画2条线呢?我们就重复使用上面两个API,如下:
1 | context.moveTo(10, 65); |
效果:
你可能已经看到了我们这里使用了context.strokeStyle='blue';
把线段的颜色改成蓝色(而不是默认的黑色),这个属性一定要在stroke之前调用,否则都描边结束了才设置,是不会生效的,这样改变的是下面描边的颜色,就好比你拿黑色的笔画了一条线,结果你又拿起了一只蓝色的笔,然后你希望你刚刚话的线是蓝色的。
这里的strokeStyle
是描边的样式,它的值可以是特殊颜色值如blue
等,也可以是rab(0,0,255)
,还可以是raba(0,0,255,1)
,更可以是#0000FF
,甚至是图片、渐变等(后面会讲到,所以没有叫strokeColor
)。
描边矩形
矩形就是4条线段,我们直接开画:
1 | context.moveTo(90, 15); |
效果:
我们绘制了一个宽高都为120px的矩形(其实也就是一个正方形)。由上可知lineTo
划线的起点是上一次移动到的地方或者上次划线结束的地方,因此我们没有必要每次都moveTo
当前位置。
由于矩形是非常重要的图形,所以canvas提供了一个更加方便的API:
1 | // 绘制一个起始坐标为:(x, y) 宽度:width 高度:height 的矩形 |
使用新的API绘制:
1 | context.rect(90, 15, 120, 120); |
这下是不是容易多了?什么?还不容易,那么给你简绍一个更简单的API:
1 | // 绘制一个起始坐标为:(x, y) 宽度:width 高度:height 的矩形 |
使用新的API绘制:
1 | context.strokeRect(90, 15, 120, 120); |
填充矩形
填充和描边一样,只是描边的时候调用的是stroke,填充的时候是fill,看一个例子:
1 | context.moveTo(90, 15); |
效果:
是不是很简单,你可能已经注意到了修改填充矩形的样式是fillStyle
,其用法跟描边时是一样的。
此时你会有一个疑问,那么描边矩形有简写吗?如果你问的话,说明你的学习力还是很不错的,先给你一个赞。当然有了,直接上代码:
1 | // 简写1 |
如果既要描边又要填充怎么办呢?可以看这个:
1 | context.rect(90, 15, 120, 120); |
效果如下,像不像CSS给了一个背景和一个边框?没错填充就类似于是设置背景,描边就类似于给个边框。
绘制简易坐标系
为了更方便后面你的使用我们绘制一个简易的坐标系吧,效果如下:
完整HTML代码如下,后面的如果不出意外的话就会在这个基础上绘制:
1 |
|