Canvas基础知识学习
作者:旺仔
最近在各个网站上看到很多关于H5的小游戏,自我觉得做的很酷炫,因为公司也有长期收集H5游戏的任务,就下载下来了很多,通过对各个游戏的代码的比对,发现这些游戏大部分都是基于H5新加的标签canvas(画布)进行开发的,在对于canvas不是很了解的情况下对下载下来的游戏代码进行更改和阅读非常困难,于是便萌生了利用工作之余的时间对canvas进行学习的念头,以下便是我对canvas学习的部分知识点的总结:(学习还在进行中,目前总结只是部分)
一、canvas标签的定义
Canvas标签为html5新添加的一个标签,其在页面里面使用就如同在html页面中使用div、p、span等标签一样简单,唯一不同的是canvas标签在html页面中的呈现效果要使用canvas标签自带的API进行渲染。
下面的内容就具体来聊聊canvas的API及简单的绘制:
二、canvas的绘制环境
就像其他 HTML 标签一样,我们也可以用 canvas标签的 height和 width属性为 canvas 指定其在页面上高度和宽度。在初始化Javascript函数中,我们可以用 canvas 标签的 id 获得 canvas 的 DOM 对象,并用 getContext()方法获得这个 canvas 的“2d”上下文对象,其后的绘图操作都将以此上下文对象为基础。具体代码如下:
window.onload = function() {
var canvas = document.getElementById("myCanvas");//获取canvas的id
var context = canvas.getContext("2d");//获取canvas的上下文环境为“2d”,之后的绘制便基于context进行
//此处便可添加具体绘制代码
};
2.1学会画一条直线
context.moveTo(100,100);
context.lineTo(300,300);
context.strokeStyle="red";
context.lineWidth=3;
context.stroke();
如代码所示:moveTo方法是设置canvas画笔的初始位置,lineTo方法是获取画笔的结束位置,strokeStyle方法是是设置所画线条的颜色,lineWidth为线条宽度;在此之前的所写的代码仅仅是收到了需要执行的预备但并没有执行;stroke方法便是对以上的一系列动作进行执行(代码中moveTo和lineTo括号内的参数分别是对应的x和y的坐标)。
当然,当一条直线有了宽度之后便会有线段端点的样式,因此这里还有一个context的属性就是lineCap,lineCap有三个值分别是butt、round、square。意思顾名思义。
2.2 画一条弧线
这里画弧线与画直线在线条颜色,宽度设置,线段顶端样式相同,唯一不同的是画弧线所用的方法与画直线所用的方法不一样。画弧线的代码如下:
Context.arc(x,y,radius,startang,endang,方向)
如代码所示弧线所用的方法为arc,其有6个参数,分别是所画弧线圆心所在位置,所画弧线所在圆的半径,所化弧线开始角度和结束角度,最后一个参数使画弧线的顺逆时针,其取值true为顺时针,false为逆时针。
2.3 画一条二次弧线
如果根据2.2节的方法画出来的弧线为圆弧,但是在实际开发中我们用到的弧线会千差万别,这节即将叙述的内容便是如何画一条不是很规则的弧线,例如:抛物线。
Context.QuadraticCurveTo(controlx,controly,endx,endy);
这里的QuadraticCurveTo方法有四个参数,controlx和controly代表着二次弧线两端切线的交点,他是这个二次弧线的核心,他控制者该二次弧线的开口方向与开口大小。endx与endy为该二次弧线的结束点位置;想要画一条二次弧线还需要一个初始点,这里的初始点要用moveTo方法来规定;即完整代码如下:
context.moveTo(startx,starty);
Context.QuadraticCurveTo(controlx,controly,endx,endy)
2.4 贝塞尔曲线
贝塞尔曲线为二次弧线的加强版本,可以更加diy自己所画的曲线样式,比如画一朵花朵或者画一朵云朵,这些在生活中不是特别规则的事物,如果用二次曲线与弧线画出来就不是那么的真实。下面就对贝塞尔曲线的具体代码及参数作一个解释:
context.moveTo(startx,starty);
Context.bezierCurveTo(controlx,controly,controlx1,controly1,endx,endy);
贝塞尔曲线与二次曲线同理,需要一个moveTo进行起始点的定位,在通过bezierCurveTo来处理贝塞尔曲线的绘制,下面是我从网上找的一张对图,可帮助我们对贝塞尔曲线做一个简单的理解。
有了上面的这张图,便很容易的对贝塞尔曲线进行理解了,控制贝塞尔曲线的核心便是controlx,controly,controlx1,controly1这四个参数。
其实,2.1/2.2/2.3/2.4小结所学习的内容是可以运用在一张画布中的,通过以上的几种线性的学习基本可以完成生活中所遇到的大多数物体的绘图。
有了几种线性的结合使用就会有线与线之间的连接:
2.5 线条链接的样式
Context.lineJoin=”round”
lineJoin很简单,有三个参数,分别是:round/miter/bevel。Round为接线处圆润,miter为尖角,bevel为方角。这里就不展开说了。
2.6图片的颜色填充
Context.fillstyle=”blue”;
Context.fill();
如代码所示,fillstyle为即将在图形上填充的颜色,fill为填充命令,即,fillstyle与fill要同时出现,只出现fillstyle不会对所画的图像进行颜色的填充;
2.7 矩形与圆形
矩形可以通过很多方法画出来,例如上面介绍到的lineTo和moveTo,只要设置好矩形的四个顶点便和容易画出来一个矩形。不过,canvas为了方便使用又定义了一个方法可直接画出矩形。
Context.rect(x,y,width,height);
绘制矩形的方法很简单,x,y为矩形左上顶点的坐标,width和height为所画矩形的宽和高。
与上面所介绍的画弧线的方法相同,画一个圆形只需要将开始和结束的角度设置为0到Math.PI*2。这里的角度全部要用弧度角表示,Math.PI*2即为2PI为一个圆周所对应的角度,就是360度。
2.8 填充渐变
在photoshop制作效果图的时候为了实现页面的丰富的效果,通常会对填充的背景进行渐变色处理,canvas也有制作这种效果的方法为:createLinearGradient与createRadialGradient。具体使用代码如下:
1.createLinearGradient 线性渐变
要使用线性渐变效果填充图形,首先要使用 createLinearGradient()方法从上下文对象中创建线性渐变对象。createLinearGradient()方法的四个参数确定一条虚拟线段,渐变就沿着此条线段的方向。然后用addColorStop方法为线性渐变对象设置渐变线上的关键点的颜色,offset表示关键点是在渐变虚拟线段的什么位置,offset的取值范围是0到1,其中0表示是起始点,1表示是终止点,0到1之间的值表示是此虚拟线段中间的某一位置。再将此线性渐变对象作为填充类型赋值给上下文对象的fillStyle 属性。canvas将根据渐变虚拟线段上关键点的颜色变化填充图形。
var grd=context.createLinearGradient(100,100,300,200);
grd.addColorStop(0.1,'aqua');
grd.addColorStop(0.9,'black');
context.fillStyle=grd;
context.fill();
2.createRadialGradient 径向渐变
径向渐变与线性渐变类似,只不过渐变方向不是线段,而是两个圆之间。使用createRadialGradient()方法创建渐变对象,参数是渐变起始圆和终止圆。
var grient=context.createRadialGradient(canvas.width/2,canvas.height,10,canvas.width/2,0,100);
grient.addColorStop(0,'blue');
grient.addColorStop(0.25,'white');
grient.addColorStop(0.5,'purple');
grient.addColorStop(0.75,'red');
grient.addColorStop(1,'yellow');
context.fillStyle=grient;
2.9图片填充
要实现图案填充功能,首先要用上下文对象的 createPattern()方法创建一个图案填充对象,将这个对象赋值给上下文对象的fillStyle属性,然后使用fill()方法填充图形。其中createPattern()方法需要两个参数,第一个参数是一个图像对象,第二个参数是重复模式,可选的模式是repeat,repeat-x,repeat-y, 以及no-repeat,默认情况是repeat。
var pattern = context.createPattern(imageObj, repeatOption);
context.fillStyle = pattern;
context.fill();
2.10 绘制图片
context.drawImage(imageObj, x, y, width, height)
如代码所示,imageObj为图片对象的路径,xy为图片左上角的坐标,即控制所绘制的图片在画布中的位置,width, height为所绘制图片的宽高;这里对图片的加载要进行说明一下:由于drawImage()方法需要一个图像对象作为参数,所以我们需要在实际调用drawImage()之前就加载图像。这一要求可以通过图像对象的onload事件来实现。
即:
imageObj.onload = function() {context.drawImage(imageObj, x, y, width, height);};
imageObj.src = "这里是图片的路径";};
2.11 一些简单的效果——阴影效果
要为图形添加阴影需要用到 shadowColor,shadowBlur,shadowOffsetX和shadowOffsetY属性。
context.shadowColor = "black";
context.shadowBlur = 20;
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
与css3类似,canvas也可以设置一个图像的阴影效果,这里的shadowColor
为你想设置的阴影效果的颜色,shadowBlur为阴影效果的虚化程度,shadowOffsetX、shadowOffsetY所绘制的阴影向x轴与y轴偏移的距离;
2.12 全局组合操作——globalCompositeOperation
globalCompositeOperation 属性定义了组合操作的方式,也就是 canvas 的源与目的的状态。目的是组合操作之前的状态,而源指的是组合操作后面的状态。globalCompositeOperation共有12种组合操作可供我们选择使用,其中包括:source-atop,source-in,sourceout,source-over,destination-atop,destination-in,destination-out,destination-over,lighter,xor,和copy。默认状态下是source-over。
如图所示,为不同组合模式下的一些状态的呈现,当一个圆形重合上一个正方形时的效果,这是一个非常强大的功能,例如,我们可以使用context.globalCompositeOperation = 'destination-out'来制作刮刮乐效果等。
2.13 位移、缩放与旋转
1、使用 translate()方法可以将绘图原点向横向和纵向移动指定的距离(x, y),结果表现为整张图像的移动。
context.translate(x, y);
2、缩放操作使用 scale() 方法,参数 x、y分别代表横向与纵向的缩放比例,两个参数都是浮点数,1.0表示不缩放,小于1.0表示缩小,大于1.0表示放大。即,原坐标(x1, y1)上的点经scale(x,y)缩放后的点将被移动到(x1*x, y1*y);
具体代码如下:context.scale(x, y);
3、旋转操作使用rotate方法,该方法所旋转的角度同arc方法画圆弧所需传入的角度值类似,都是使用弧度制计角度方法进行传值;圆心为translate的位移角度所取的位移角相同;
具体代码如下:context.rotate(angle);
注:angle即为所传入的角度。
三、总结
以上是我最近学习的canvas的一部分内容,还有许多内容没有写上来,因为canvas是一个非常强大的html5新加功能,想要学习的比较精还需要花大量时间进行深度学习,例如我目前正在学习的canvas动画和以后即将学习的canvas碰撞检测以及更深层次的游戏开发和移动端游戏开发。
在学习canvas动画时便会发现,canvas给你封装了一个requestAnimationFrame(animate)方法,他所要传的animate参数是程序开发人员自己写的一个动画方法,requestAnimationFrame仅仅是给浏览器提供一个标识,能让浏览器通过监测其机器的性能来计算下一帧动画执行的具体时间,这里的重点就是这个animate函数,这就要求canvas动画编写程序者要有一个扎实的js基础,所以在前端的学习中,html和css是最基本的技能要求,想要在前端行业上更上一层楼还要对js知识做一个系统认真的学习。
2017年9月8日