HTML5- Canvas入门(七)

这是本系列的最后一篇入门文章,主要是对剩余的未说明的canvas方法来逐个介绍。javascript

首先,若是你是一名擅长矢量设计的设计师,对Illustrator或者Fireworks很熟悉的话,那你确定知道它们有一个很强大的矢量混合处理功能,能够对多个矢量路径进行“合并”、“拆分”、“结合”、“相交”等系列操做。 以下图,在Fireworks中有三个矢量路径,我先把灰色的圆形和粉红色的矩形进行了“结合路径”的处理,接着又把结合后的路径跟绿色的星形矢量进行了“合并路径”操做:html

在canvas中也有实现一样功能的属性—— globalCompositeOperation,利用它,能够实现对画布上已有的图像(暂称为“目标图像”)和新绘制的图像(暂成为“源图像”)来执行相关的混合处理。java

globalCompositeOperation的可取值见下表:git

描述
source-over 默认。在目标图像上显示源图像。
source-atop 在目标图像顶部显示源图像。源图像位于目标图像以外的部分是不可见的。
source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
source-out 在目标图像以外显示源图像。只会显示目标图像以外源图像部分,目标图像是透明的。
destination-over 在源图像上方显示目标图像。
destination-atop 在源图像顶部显示目标图像。源图像以外的目标图像部分不会被显示。
destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
lighter 显示源图像 + 目标图像。
copy 显示源图像。忽略目标图像。
xor 使用异或操做,对源图像与目标图像进行结合处理。

咱们绘制一个蓝色的圆形和一个粉红色的矩形,对它们进行相似上图“结合路径”(xor)的处理:github

<canvas id="myCanvas" width="300" height="200" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); 
ctx.arc( 80, 80, 40, 0, 2*Math.PI);
ctx.fillStyle = "#4DA6FF";
ctx.fill();
ctx.fillStyle = "#FF7373";
ctx.globalCompositeOperation="xor";  //异或结合处理
ctx.fillRect(95,50,100,90);
</script>

效果以下:
web

各globalCompositeOperation 属性值的最终效果能够参考下图(蓝色矩形为目标图像,红色圆形为后续新绘制的源图像):canvas

接着介绍 isPointInPath() 方法,它接受一个指定点的坐标值做为参数,可判断该指定点是否位于当前路径内,并返回对应的Boolean值。
咱们来绘制一个矩形,而后判断点(115, 70)是否位于该矩形路径内部,若是是,则填充该矩形,不然alert出相关信息:后端

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.rect(95,50,100,90);
if (ctx.isPointInPath(115,70)){  //判断点(115,70)是否位于当前路径内
    ctx.fillStyle = "#FF7373";
    ctx.fill();
}else{
    alert("不在矩形路径内");
}
</script>

因为该点是位于矩形路径上的,故成功绘制矩形,而不会弹窗:api

 咱们常规使用canvas绘制多个图片的时候,总有一些会重复使用到的状态,好比咱们先绘制了一个“倾斜20度、填充颜色为红色”的矩形,接着绘制了一个“不倾斜、填充颜色为蓝色”的矩形。若是后面咱们又要重复绘制一个“倾斜20度、填充颜色为红色”的矩形,又得从新设置画布的setTransform和fillStyle值,天然是挺烦人的事情。
canvas的 save() restore() 方法便能为咱们处理这个问题——使用 .save() 方法能为咱们保存当前画布的状态,使用 .restore() 方法能够把当前画布状态返回到上一次保存的状态,有点相似于咱们玩游戏过程当中存档和读档的功能。
咱们先说说canvas的“状态”,它指的是像咱们上面提到的“倾斜(变形)、填充”这样的配置,是当前全部样式和变形的一个快照。咱们能够保存和读取到的状态包括:浏览器

当前的 transformation matrix;
当前的 clipping region;
当前的属性值:fillStyle, font, globalAlpha,
globalCompositeOperation, lineCap, lineJoin,
lineWidth, miterLimit, shadowBlur, shadowColor,
shadowOffsetX, shadowOffsetY, strokeStyle, textAlign,
textBaseline

canvas的状态是以栈(stack)的方式保存的,遵循先进后出(FILO)原则。每一次调用 save 方法,当前的状态就会被推入栈中保存起来;当调用 restore 方法时,最新入栈的状态则被推出使用。
咱们来一个简单的例子:

<canvas id="myCanvas" width="150" height="150" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(20,20,100,100);
ctx.save();  //保存状态(fillStyle = "green")
ctx.fillStyle = "red";
ctx.fillRect(40,40,60,60);
ctx.restore();  //读取上次保存的状态(fillStyle = "green")
ctx.fillRect(60,60,20,20);   //填充了绿色的矩形而非红色的
</script>

效果以下:

上面的例子很好理解,不过为了了解“状态入栈出栈”的状况,咱们把上面例子改造一下:

<canvas id="myCanvas" width="150" height="150" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "yellow";  //注意这里多了一行状态定义
ctx.save();    //注意这里多了一行状态保存
ctx.fillStyle = "green";
ctx.fillRect(20,20,100,100);
ctx.save();
ctx.fillStyle = "red";
ctx.fillRect(40,40,60,60);
ctx.restore();   //推出最后一个入栈的状态(fillStyle = "green")
ctx.restore();   //再次推出最后一个入栈的状态(fillStyle = "yellow"),注意green已经在上次restore推出了,故此次取到的是yellow
ctx.fillRect(60,60,20,20);  //填充黄色的矩形
</script>

就像注释说明的那样,最终绘制的小矩形是黄色而非绿色:

最后介绍的是 toDataURL() 方法,它能把当前画布的内容转换为data类型的URL格式。 等等,“data类型的URL格式”又是什么来的? 有时候咱们会在某些页面(好比github404页面)看到这样的图片:

其src对应的是一串“data:image/png;base64....”的data类型URL格式,返回的base64图片数据流,能够减小对服务器的图片请求(固然缺点是没法缓存在客户端)。这种格式这就是咱们上面提到的东西。 那么 toDataURL() 方法的好处就显而易见了——咱们能够把当前画布内容转换为一张图片。

toDataURL() 方法直接做用于canvas对象,而非context2D对象,其格式为:

url = canvas.toDataURL( [ type, ... ] )

参数type表示返回文件的MINE类型,若未指定type,则默认返回的格式必须为PNG格式。若是canvas没有任何像素,则返回值为:“data:,”,这是最短的data:URL,在text/plain资源中表现为空字符串。
type的值能够在image/png,image/jpeg,image/svg+xml 等MIME类型中选择。若是是image/jpeg,能够有第二个参数,若是第二个参数的值在0-1之间,则表示JPEG的质量等级,不然使用浏览器内置默认质量等级。

咱们来个小例子:

<canvas id="myCanvas" width="150" height="150" style="border:solid 1px #CCC;"></canvas>

<button onClick="openImg()">点我查看图片</button>

<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(20,20,100,100);
ctx.save();
ctx.fillStyle = "red";
ctx.fillRect(40,40,60,60);
ctx.restore(); 
ctx.fillRect(60,60,20,20); 

function openImg(){
    var image = c.toDataURL("image/png"),  //注意toDataURL是canvas对象方法,而不是context2D的属性
         w  = window.open('about:blank'); 
    w.document.write("<img src='"+image+"' />"); 
}
</script>

点击“点我查看图片”的按钮后会弹出一个新页面,上面有咱们生成的base64编码形式的图片(跟canvas上绘制的内容一致):

但因为该图片是不存在于任何文件目录上的,天然也没法直接下载该(带后缀名的)文件,若是想要地道地生成一张图片供用户下载,则须要后端配合了(能够参考这里)。
另外有一点要注意的,也就是咱们在第五章提到的,若是在canvas中绘制了非本地的图片,从安全性考虑将没法对其进行读操做,这种状况下若是执行toDataURL天然也会报错。不过若是资源开启了CORS,则有办法避开同源策略的阻拦(能够参考这里)。

自此,canvas的api咱们基本都遍历了一遍,但愿能让来此学习的朋友有所收获,共勉~

相关文章
相关标签/搜索