下面开始真正的开发一个小游戏
这里首先介绍canvas所有接口的使用。包括beginpath,closePath,linejoin,miterlimit,translate,rotate,scale,linecap。
本课开始前,要知道canvas的创建,如何绘制直线,多边形,弧线,圆。
更加复杂的动画过程,还要等绘制学完之后,才能攻克。
每个接口一个小的示范性程序,启示如何将这些接口使用在真实的环境中。
Canvas基础回归:
绘制一条直线
在HTML中 <canvas id="canvas"> </canvas> 创建canvas标签。
在JavaScript中
var canvas = document.getElementById("canvas") //获得canvas一个变量
var context = canvas.getContext("2d") //获得canvas的一个2d的绘图上下文环境。
//使用context进行绘制。canvas绘图的所有接口都是使用context的这个上下文环境提供。
目前只进行2d绘图,3D是截然不同的。

context.moveTo(100,100)是笔尖放到这个地方,然后context.lineTo(700,700),将要画到这个地方,但是这里注意,只是一个状态,而context.stroke()才是画出来。

首先创建一个canvas标签,也像其他标签一样,可以设置相关的样式。然后在js中,获取这个canvas,设置宽高,画线。


canvas是基于状态的绘制,所以都是先设置好状态,然后绘制。那么还有什么状态呢?这里有线的宽度,linewidth和strokeStyle。宽度和线条的样式。这里主要是颜色。也就是说,canvas是基于线条的状态绘制,不是基于对象。我们不是先创建一个canvas的对象,然后设置它的各个属性。对整体设置状态,然后绘制。

如何画折线?再来一个lineTo

同样画一个多边形,一个moveTo,多个lineTo,画一个箭头。

一个moveTo,一次起笔。
如果要绘制三条不同颜色的折线怎么做呢?分析下面代码对不对?

这是有问题的。因为canvas是状态加绘制。所以下面的状态会覆盖上面的状态。所以效果是下面:

第一段绘制没问题,但是第二段绘制的时候,context.strokeStyle=“green” 覆盖了上面的颜色。同样第三次,会将上面所有的线又绘制了一遍,将所有状态完成一次绘制。为蓝色。
引出:context.beginPath(),声明从现在开始要进行一段全新的绘制。当使用beginPath之后,再指定新的路径,再调用绘制的函数,比如stroke(),将绘制从context.beginPath()到context.stroke()之间的状态来进行具体的绘制。

每个beginPath都是一个从新开始绘制。

注意context.lineWidth=10,一直在最前面,在context.beginPath()之后,如果一个属性一直没有覆盖的话,将一直保持该状态。而strokeStyle一直被覆盖,所以将用被覆盖的属性值。一定要区分什么属性被覆盖,什么属性一直保持着。
第一个beginPath可以省略。
beginPath开始一个全新的路径,moveTo从某点开始,lineTo画到这个点。当使用beginPath之后,第一个moveTo可以换成lineTo,因为上一个坐标点被beginPath清空了。

绘制封闭的图像,只要首位相连就好了


但是有一个小瑕疵,就是缝合处。因为线段比较宽,如果比较窄,一个像素,就不会有这个问题。
更好的封闭的方法,就是beginPath喝closePath成对出现,那么画出来的形状就是封闭的。





现在就完美封闭了。关于closePath还有一点,如果最后一个lineTo没有写,依然是自动用直线将最后一个点连接第一个点。


一个填充的颜色,加一个进行填充。下面具体例子:


里面有了填充色,而且线条有10个像素,但是里面的5个像素被填充了,要解决这个问题,肯定是先填充,后对线条描边。


fillstyle和strokeStyle都是对状态的定义。context基于状态的绘制的,所以可以把所有的状态放在一起,再把所有的绘制放在一起,这样也是不影响结果的。如下
context.lineWidth = 10
context.fillStyle = "yellow"
context.strokeStyle = "#058"
//以上都是状态
context.fill()
contex.stroke()
//进行绘制

传入参数,cxt上下文环境,就是传入的context,x,y绘制的起始位置。矩形的宽和高,边框的宽和颜色,填充色。


绘图中矩形比较多,所以有专门的矩形绘制函数,rect(x,y,width,height),绘制的起点,宽和高。

这两个结果是一样的。还有更方便的两个:

fillRect使用当前的fillStyle,而strokeRect使用strokeStyle绘制当前的矩形边框。和rect()区别是,rect()状态,还需要绘制一下,但是fillRect和strokeRect直接绘制出来了。

看这两个有区别的。

后绘制的图形会遮挡前面绘制的图形。

支持css支持的样式






线条的属性
linewidth就是线条属性的一种
线条的帽子:lineCap
设置线条两端的情况,默认是butt,还可以是round和square,圆头和方头。
具体如下:



round是一个圆形的头,square是方形的头。butt是没有的。注意lineCap只能用于线段的开始和结尾处,不能用于线段的连接处。

在开始的地方,是圆头,都是在连接的地方,是尖角。

上面没有beginPath和closePath时候,最后的连接是不缝合的。

加上context.linCap = ''square''时候

由于square是方形的头,所以会自动补上。但是闭合的图形,还是建议使用beginPath和closePath。
画一个五角星


大圆上五个点,小圆上五个点,可以求出右边大圆上和小圆的点,下一个点相差72度,所以可以通过一个循环,遍历五个点。

cos和sin函数里先角度转弧度。400是将圆心给移动一下。
为了能复用这个五角星,给它一些变量:r小圆半径,R大圆半径,x,y圆心偏移量。

调用一下drawStar(context,150,300,400,400)就可以了。
再改进一下,增加一个rot,旋转的角度。

转30度之后的样子

线条的链接:lineJoin和miterLimit
lineJoin线条和线条相交的时候,所呈现的状态,默认miter尖角,bevel谢姐,round圆角形式。
尖角如下:

context.lineJoin=bevel 斜接是下面这个样子:

线条顶端不会成一个角。round是下面样子


看一下miterLimit的含义,默认是10个像素。只有lineJoin为miter的时候会有这个限制,如果超miterLimit过10个像素,就会把lineJoin变成bevel形式。如下:

lineJoin为miter的时候,应该是尖角,但是把内圆改小一些,让尖角更尖。实际如下,因为超过了10像素。

但是把miterLimit改成20之后,就可以正常显示了




图形变换

改造画一个五角星的函数,设置填充色和边缘色。
之后在onload函数里面绘制一个黑色背景,

填充矩形背景大小与canvas一样。填充色为黑色。

写一个循环,画200个随机的星星

random为随机生成0-1,然后半径为10-20,小圆半径为大圆的一半。x,y的位置在canvas里面随机,旋转角度a为0-360里随机。每次刷新效果不一样。两个优化:有些星星在外面,另外有些星星叠在一起。

上面的drawStar在功能上已经能完全满足功能了。但是承载功能太多。比如下次想画一个四角星,甚至小圆点,改起来就比较麻烦了。为了解决这个问题,

这是一个绘制五角星的函数,在0,0位置,半径为1,同时没有任何偏移,没有任何旋转的五角星。把这样的五角星称为标准五角星。

在drawStar中,先绘制一个标准的五角星,然后再位移,改大小,旋转角度。比如之后要绘制4角星,八角形,只需要更改starPath就好了。同时这里的starPath也可以作为参数进行传递。图形学里,都是这种绘制,先绘制基本的图像,再进行旋转,改变大小等图形变换。

最常用的三种图形变换。

translate把基坐标的(0,0)点放到了(100,100),然后绘制。效果如图:

但是有一个小陷阱:


两次之后,第二个矩形的位置,并不是300,300.而是400,400.因为基坐标的位置发生两次变化。图形变换函数是叠加的。为了避免这个陷阱,可以方向操作一下:


但是逆转太麻烦,canvas使用save和restore,用来存储状态,返回状态。

这两个成对出现,保证canvas图形绘制状态的正确。先固定一下starPath中星星的大小。

首位先保持和恢复状态。对星星translate改变位置,然后旋转角度,绘制星星,填充色,边缘色,线宽,线交合处,填充,描边。完成后如下:

上面星星大小是一样的,下面看一下使用scale产生什么问题,如下演示程序:

以上画三个正方形,位置都是从50,50开始画,大小都是200,200,但是实际效果如下:

不仅大小改变了,左上角的坐标也进行了操作,线条的宽度也改变了。scale是有副作用的,比如线条大小,左上角的坐标,这个是要注意的。

绘制大小随机的星星的时候,只能是放弃边框的绘制了,然后一个改变大小scale。
程序运行的效果如下:

注意缩放的副作用。可能会放弃一些东西的绘制,或者用我们自己的方法绘制。

深入理解图形变换:


这样一个函数可以代替三个。


这里把水平方向缩放改成2,垂直方向改成1.5。


依然有之前的两个负效果,位置和边框都改变了、


在水平和垂直方向倾斜0.2的效果。


每次变换的效果是在上一次的效果之上的。级联的。但是setTransform可以无视之前的transform的效果。

之前的倾斜都无效了。



填充样式
fillStyle 除了颜色,还可以其他的。线性渐变色和镜像渐变色。

四个变量,两个坐标,构成一个线段。渐变线,构成渐变方向和尺度。

第一个stop关键色的位置,第二个color关键色是什么颜色。下面例子:

第一个addColorStop 中0.0就是起始位置,为白色,第二个addColorStop 中1.0就是终止的位置,为黑色。这样就是从左上角0,0到右下角800,800由白至黑的一个渐变色。

几个注意点
1、创建linearGrad之后,addColorStop可以添加无数个的。自己喜欢的顺序添加颜色就好。

渐变线还可以水平和垂直的。

还可以只指定一部分,不是全部画布的。

创建一个渐变到400,400,渐变结束后,其他部分显示的是渐变的结束时候的颜色。
还可以超过画布的最大值。外侧的黑白色不会显示了。


根据上面的渐变色可以改变星空的样式。创建一个渐变色,从0,0到0,canvas.height,也就是贯穿整个屏幕的垂直方向。增加两个颜色,起始点是黑色,终点是深蓝。然后把星星变小一些,另外星星的排布在上0.65的区域。如下显示:

放射性的渐变:Radial Gradient

两个同心圆的基础上,6个参数:第一个圆圆点半径,第二个圆圆点半径,整个径向渐变就发生在这两个圆环之间。

第二个添加颜色。

圆心400,400,半径0,就是一个点,外面圆圆心一样,半径500。添加5种颜色,

内圆半径如果非0,如下:

这个圆白色,外面超过500个像素的半径为黑色。

星空中,径向渐变开始于底边中点,如下所示:

createPattern


下面分别是no-repeat,repeat-x和repeat-y的样式




同样canvas画布也可以作为填充方式。

创建了一个backCanvas画布,然后作为填充。

创建画布,设置高宽,画星星。创建好的画布返回。
效果如下:


video也可以作为背景填充。





同样,fillstyle也可以应用与strokestyle上面。
曲线的绘制


6个参数,圆心坐标,半径,开始和结束的角度,顺时针还是逆时针。
看这几个绘制:第一个画10个弧,第二个弧是闭合的,

第三个个逆时针,



圆角矩形

绘制圆角矩形就可以分成上面8个部分。确认圆心就可以了。


调用drawRoundRect就可以了。


已知的有(x0,y0),根据(x1,y1),(x2,y2)绘制两条直线,然后圆弧与这两个直线相切,半径为radius。下面具体使用:

绘制了一条圆弧和一个条辅助线。

注意,起始点不一定是圆弧的开始点,另外圆弧的结束点也不一定是终止点,而是切线终止点。起点不一定是切点,停止于切点,不是终点。

一个绘制圆弧的函数,三个点,一个半径。
如果半径过大,会从起点开始延长到切点,然后开始画,画到的也不是终点,而是延长线上的切点。





贝塞尔曲线 Bezier

以下二次贝塞尔曲线:

http://blogs.sitepointstatic.com/examples/tech/canvas-curves/quadratic-curve.html
网站可以查看贝塞尔曲线绘制效果。
第一个点是控制点,第二个点是终止点。二次曲线不能绘制波浪线。
以下三次贝塞尔曲线:

http://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html

有两个控制点,前两个是控制点,最后一个是结束点。
另外二次曲线不能像这样外部扩张







context.font 字体的样式,fillStyle填充的颜色,fillText 填充的字体,后面参数是填充字体的位置。


第四个参数是最大的长度,如果设为400,效果如下







默认是大小和字体,可以设置五个属性。font-style默认normal ,italic斜体字,oblique倾斜字体。

web中可能看不出来italic和oblique的区别。

自己导入的字体,可能斜体和倾斜有区别。



小型大写字母

normal通常指400,同理bold





文本对齐





网友评论