canvas学习总结(三)
上篇文档中介绍了canvas图形绘制技巧并制作了几个典型的案例。本文档主要在上篇基础上继续扩展讲述Canvas的图形样式渲染技巧。本篇资料参考来自:dev.w3c.org。
1 线风格
正如前面所讲,线也有风格,我们经常设置的是线宽(lineWidth);
context.lineWidth [=value];// 返回或设置线宽,value以像素为单位。
还有几个其他的线风格:
线帽(lineCap):
context.lineCap[=value];//value:butt/round/square
butt:默认值,不做任何处理;
round:头尾增加半圆形的箭头;
square:头尾增加长方形,长为线宽1/2,高位线宽;
连接方式(lineJoin):
context.lineJoin[=value];//value:miter/round/bevel
miter:默认值,外延交于一点,外延的斜率可以由miterLimit属性显示定义;
round:连接外延为以内侧交点为圆心,以线宽为半径的圆角;
bevel:斜角连接
斜角斜率(miterLimit):
context.miterLimit[=value];//value:默认值为10.0
miterLimit表示斜接长度:如下图示:

我们发现,边角角度越小,斜接长度越大,为了避免斜接长度过大,我们使用miterLimit属性进行限制,且只有当lineJoin=‘miter’时,该属性才有效;
记斜接长度为l,则有下列结论:
- l<=0,忽略;
- 0<l<=value,尖角显示;
- l>value,边角以bevel类型显示(以连接线垂直方向截断);
下面是关于lineJoin属性的演示:

2 字体样式
context.font[=value];//获得或设置文字类型
eg: context.font = '10px sans-serif';
上面是font的默认值。font可以设置的属性按顺序排列如下:
font-style:normal/italic/oblique;//字体样式
font-variant:normal/small-caps;//字体变体
font-weight:normal/bold/bolder/lighter/100…900;//字体粗细,默认400
font-size/line-height:规定字号和行高,以像素计,默认:10px/2;
font-family:规定字型,默认sans-serif;
文字对齐:
context.textAlign[=value];//获取或设置文字对齐方式。
value可取值:start(默认)/end/left/right/center
设置文字的对齐基线:
context.textBaseline[=value];//获取或设置文字的对齐基线
value可取值:alphabetic(默认)/top/bottom/middle/hanging/ideographic

3 颜色及渐变
正如前面所述canvas中通过设置context.fillStyle和context.strokeStyle两个属性值设置绘制的颜色。前者表示填充颜色,后者表示路径颜色。色值均通过RGB属性获得:
fillStyle = “#F00”;//#FF0000的简写
fillStyle = “red”;//用自然语言描述
fillStyle = “rgb(255,0,0)”;//显示定义rgb的值(0~255)
fillStyle = “rgba(255,0,0,0.6)”;//带透明度的颜色设置,0~1,0表示完全透明
canvas除了可以定义纯色,还可以自定义颜色渐变。canvas定义了CanvasGradient接口:

addColorStop方法规定gradient对象中的颜色和位置,偏移量(offset)取0~ 1.0,color为一个DOM字符串,用法如下:
gradient.addColorStop(0,’rgba(200,0,0,0.7)’);
当需要使用多个渐变的混合效果时可以多次调用此方法。
利用canvas对象可以为此接口生成gradient对象。
1.0规范规定了两类渐变类型:线性渐变和径向渐变:

两个方法都返回CanvasGradient对象。具体参数的含义如下:
线性渐变的参数较简单,分别表示2个点的坐标,下面是一个简单的黑白渐变:

代码展示:

下面是多个线性渐变混合的效果:

代码展示:

径向渐变前3个参数和后3个参数分别表示开始圆和结束圆。
把它想象成手电筒照出的光柱,光柱外都以透明黑填充,光柱开始圆至向外延伸的部分以偏移量为0的纯色填充;光柱结束圆至向外延伸的部分以偏移量为1的纯色填充。显然如果两个圆半径相等则两端向外无限延伸,否则总会在某端聚焦于一点,而中间区域会以(x1,y1)为圆心,以半径为r1+w的范围内变化,且同一半径下圆弧上点的色值相等。下面是该效果的示意图:


代码展示:

4 图案平铺
通常页面上的一些底纹效果是通过图案平铺效果展示出来的。在canvas画布里也可以轻松实现图案平铺。我们可以使用下面这张小图片(96*96)实现画布背景平铺效果:


canvas1.0定义了CanvasPattern接口:

通过canvas上下文对象可以创建CanvasPattern对象,方法定义如下:

这个方法第一个参数:image指的是Html中的image,canvas或video元素;第二个参数repetition指的是重复方式,其值有:
repeat:默认值,水平和垂直方向重复;
repeat-x:只在水平方向重复;
repeat-y:只在垂直方向重复;
no-repeat:不重复;
被重复的元素可以用于绘制/填充矩形、圆形或线条等等。
下面是上面例子的代码:

除了可以用图案进行平铺还可以用图案进行绘制,就像ps里的画刷一样,只要指定strokeStyle=pattern即可。
5 阴影
关于阴影设置有四个全局的属性:
context.shadowBlur[=value];//获取或设置阴影的模糊等级,value>0,相当于PS里羽化效果;
context.shadowColor[=value];//获取或设置阴影的颜色;
context.shadowOffsetX[=value];//获取或设置阴影横向偏移;
context.shadowOffsetY[=value];//获取或设置阴影纵向偏移;
下图是一个带阴影的圆形按钮:

代码展示:

6 滤镜特效
如果说canvas的渲染能力有多强,必须要提到canvas所能展现的各种滤镜特效。
玩过ps的人应该都知道用过滤镜。通过滤镜设置可以展现出各种特效,比如反色、分层云彩、浮雕、影印等。
canvas之所以能实现各种滤镜效果,是因为canvas支持对图像进行像素级操作,通过一定的算法对像素的rgb值进行变换,从而达到特殊的效果。
首先,介绍下w3c canvas 1.0里的一些规范。
canvas 1.0里定义了ImageData接口:

ImageData里封装了图像的像素值:width、height、data。width和height表示像素的长宽比,data是个Uint8ClampedArray对象。
下图是对该对象的官方解释:

canvas提供的像素级操作的方法主要有以下几种:
createImageData、getImageData、putImageData,方法定义如下:

参数含义如下:
createImageData可以通过指定css像素宽高或从一个ImageData中获取宽高的的ImageData对象,所有像素为透明黑(transparent black);
getImageData通过给定的画布上矩形区域返回该区域内的图像,对于区域外的部分返回透明黑;
putImageData在当前画布上绘制ImageData对象,如果指定了脏矩形(dirty rectangle注1)则只有脏矩形上的数据被绘制。
好了,来进行实战演练吧。
下面我们实现ps里溶图的效果(注2):

上图的第三张图是第一张图和第二张图叠加的结果。
代码展示:

我们将融合效果封装到Effects的blend方法中。其算法如下:

blend通过调用底层方法:_darken实现像素变暗的效果,这是整个算法的核心:

每种效果都有一个核心算法,这个算法可以在网上找到。当然你也可以创造特定的算法。
其实,滤镜特效的展现属于像素化操作(pixel manipulation)。通过js就可以随心所欲地控制图像像素,甚至可以对特定的像素块进行循环变换,从而产生动画效果,甚至比用一般2d游戏做出来的效果更加细腻!
本篇展示的渲染均是静态渲染,后续会做些简单的动态渲染以及简单的小动画。
7 综合演示
优化钟表样式
上篇最后我们绘制了一个钟表,现在我们优化下钟表样子:
第一步:给矩形表面添加纹理

代码展示:

第二步:给圆盘添加渐变

代码展示:

第三步:添加阴影

代码展示:

注解:
注1:脏矩形是二维图像引擎里的一个专用术语。2d游戏中把只进行局部更新的区域为“脏矩形”。具体解释请进行百度或google搜索。
注2:此例引自http://www.w3cfuns.com/。里面有很多好的例子。
浙公网安备 33010602011771号