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

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

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

globalCompositeOperation的可取值见下表:

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

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

<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>

效果如下:

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

接着介绍 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>

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

我们常规使用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我们基本都遍历了一遍,希望能让来此学习的朋友有所收获,共勉~

HTML5- Canvas入门(七)的更多相关文章

  1. HTML5 canvas入门

    HTML5 Canvas入门 <canvas> 标签定义图形,比如图表和其他图像,您必须使用脚本来绘制图形.在画布上(Canvas)画一个红色矩形,渐变矩形,彩色矩形,和一些彩色的文字. ...

  2. html5 Canvas绘制图形入门详解

    html5,这个应该就不需要多作介绍了,只要是开发人员应该都不会陌生.html5是「新兴」的网页技术标准,目前,除IE8及其以下版本的IE浏览器之外,几乎所有主流浏览器(FireFox.Chrome. ...

  3. HTML5 canvas绘制线条曲线

    HTML5 canvas入门 线条例子 1.简单线条 2.三角形 3.填充三角形背景颜色 4.线条颜色以及线条大小 5.二次贝塞尔曲线 6.三次贝塞尔曲线 <!doctype html> ...

  4. Canvas入门笔记-实现极简画笔

    今天学习了Html5 Canvas入门,已经有大神写得很详细了http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html#8 在学习过后 ...

  5. HTML5 Canvas 画图入门

    HTML5 Canvas 画图入门 HTML5 Canvas 画图入门,仅供学习參考 <!DOCTYPE html> <html> <head> <meta ...

  6. 赠书:HTML5 Canvas 2d 编程必读的两本经典

    赠书:HTML5 Canvas 2d 编程必读的两本经典 这两年多一直在和HTML5 Canvas 打交道,也带领团队开发了世界首款基于HTML5 Canvas 的演示文档工具---AxeSlide( ...

  7. 03.Web大前端时代之:HTML5+CSS3入门系列~H5功能元素

    Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 2.功能元素 1.hgroup 对网页或区段(secti ...

  8. 06. Web大前端时代之:HTML5+CSS3入门系列~HTML5 画布

    Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 我们先看看画布的魅力: 初始画布 canvas默认是宽3 ...

  9. 使用html5 canvas绘制图片

    注意:本文属于<html5 Canvas绘制图形入门详解>系列文章中的一部分.如果你是html5初学者,仅仅阅读本文,可能无法较深入的理解canvas,甚至无法顺畅地通读本文.请点击上述链 ...

  10. 使用html5 canvas绘制圆形或弧线

    注意:本文属于<html5 Canvas绘制图形入门详解>系列文章中的一部分.如果你是html5初学者,仅仅阅读本文,可能无法较深入的理解canvas,甚至无法顺畅地通读本文.请点击上述链 ...

随机推荐

  1. Hadoop单机模式安装-(1)安装设置虚拟环境

    网络上关于如何单机模式安装Hadoop的文章很多,按照其步骤走下来多数都失败,按照其操作弯路走过了不少但终究还是把问题都解决了,所以顺便自己详细记录下完整的安装过程. 此篇主要介绍如何在Windows ...

  2. 【leetcode】Remove Nth Node From End of List

    题目简述: Given a linked list, remove the nth node from the end of list and return its head. For example ...

  3. 基本术语表【WF】

    术语 定义 activity(活动) Windows Workflow Foundation 中的程序行为单元. 可将单个活动组合在一起,形成更复杂的活动. activity action(活动操作) ...

  4. 第三十四篇:在SOUI中使用异步通知

    概述 异步通知是客户端开发中常见的需求,比如在一个网络处理线程中要通知UI线程更新等等. 通常在Windows编程中,为了方便,我们一般会向UI线程的窗口句柄Post/Send一个窗口消息从而达到将非 ...

  5. SPFA

    SPFA算法用来求单源最短路.可以处理任何有解的情况. 先建一个数组\(dist_x = 起点到x的最短路长度\),当\(x=起点\)时为0,当x和起点不通时为INF(本题中为\(2^31-1\)). ...

  6. AES加密解密通用版Object-C / C# / JAVA

    1.无向量 128位 /// <summary> /// AES加密(无向量) /// </summary> /// <param name="plainByt ...

  7. pythony语法小练习

    i=[0,1] b=[2,3] print(dict([i,b]))#列表转换为字典 题目:有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析:可填在百位.十位 ...

  8. centos 研究

    默认工具: yum , (Ubuntu: apt-get)

  9. Apple、Google、Microsoft的用户体验设计原则

    轻巧的Apple 注重设计过程: 在设计过程中引入用户交互的5个目标: 了解您的目标客户 分析用户的工作流 构造原型系统 观察用户测试 制定观察用户准则 做出设计决定 避免功能泛滥 80% 方案 优秀 ...

  10. android 腾讯x5内核 浏览器

    1.浏览器内核: 主流浏览器内核介绍(前端开发值得了解的浏览器内核历史) 浏览器内核历史介绍: 在android 4.4之前,浏览器用的还是webkit 在android 4.4之后,google就抛 ...