让自己也能使用Canvas
<canvas> 是 HTML5 新增的元素,可使用JavaScript脚本来绘制图形。例如:画图,合成照片,创建动画甚至实时视频处理与渲染。
兼容性方面,除了一些骨灰级浏览器IE6、IE7、IE8等,大部分现代浏览器都能支持。
一、属性与方法
1)属性
<canvas> 看起来和 <img> 元素很相像,唯一的不同就是它并没有 src 和 alt 属性。实际上,<canvas> 标签只有两个属性—— width和height。
<canvas id="strick" width="150" height="150"></canvas>
还有些默认的属性,id、style等
2)方法
1. getContext(in DOMString contextId)
canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。这个方法是用来获得渲染上下文和它的绘画功能。
contextType中可选的参数有“2d”、“webgl”、“webgl2”、“bitmaprenderer”。
如果是“2d”,就会返回 CanvasRenderingContext2D 对象。如果是“webgl”,就会返回 WebGLRenderingContext 对象。
contextAttributes属性会根据 “2d” 或 “webgl” 会需要不同的参数。
var canvas = document.getElementById('strick');
var ctx = canvas.getContext('2d');
2. toDataURL(in optional DOMString type, in any ...args)
返回一个data: URL,将canvas中的图片编码成字符串形式,有多种格式选择,type参数的默认值为image/png。
曾做过一个图片合成的功能,就使用到了这个功能。这里要注意一个“画布污染”。
就是嵌入的图片是跨域的,那么就不能使用这个方法。在《预览、旋转、合成》做过简单的分析。
3. toBlob(in Function callback, in optional DOMString type, in any ...args)
返回一个Blob(binary large object)对象。Blob代表了一段二进制数据,就是一个包含只读原始数据的类文件对象。
在《移动端图片操作(一)——上传》曾做过简单的介绍。
二、绘制2D图形
这里绘制的是2D图形,会用到 CanvasRenderingContext2D 对象中的属性或方法。
在MDN上面有个基础教程《Canvas教程》,覆盖面蛮全的。
1)坐标空间
画布的起点为左上角,这个起始点通过方法 translate 可以自定义,例如做旋转缩放等操作。
上图所示,canvas的坐标轴与普通的坐标轴是相反的。
所以顺时针是正值,逆时针是负值。
2)绘制形状
矩形是canvas支持的唯一一种原生的图形绘制。要画其他形状,就需要通过绘制路径实现。绘制矩形提供了3个方法。
路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。有操纵路径和绘制路径(包含贝塞尔曲线)的方法。
操作过程大致为4步,先创建路径起始点,再画出路径,然后闭合路径,最后填充。
1. 简单图形
下图中是些简单的图形,两个三角形中有一个是旋转了画布的,逆时针画的半圆,三个圆圈与一个半圆组成的笑脸,用贝塞尔曲线画的对话气泡,可以在线调试下面的效果。
2. 复杂图形
在CSS中,边框、字体等都能设置宽度、大小、颜色等,高级点的还有阴影、渐变、rgba等。
在canvas中也有相应的操作,绘制文本、线型、文本样式、填充和描边样式、渐变和图案、阴影。
有网友画了头灰太狼,非常逼真,可以在线调试,通过查看源码,里面用到的就是beginPath、moveTo、quadraticCurveTo等路径相关的方法或属性。
3)使用图片
canvas可以对图片进行合成、缩放、裁剪、旋转、变形等操作。
a. 简单的合成
现在有些网站会让你DIY做张海报,然后分享到朋友圈。前段时间做了个简易的海报,仅仅是将图片合成在一起,没有做涂鸦等操作,详细的介绍可以查看《移动端图片操作系列》
b. 高级点的合成
高级点的制作海报,能够输入自定义的文字,用到了上面所说的绘制形状的一些概念,在看源码的时候,发现引用了脚本“hidpi-canvas-polyfill”,解决canvas 在高清屏下绘制图片变模糊。
![]() |
![]() |
简单合成 | 高级合成 |
除了基础的操作,还有高级的像素操作,获取图片中某一像素的RGBA,然后修改其中的R、G、B或A的值,来修改颜色或透明度。
例如鼠标移动获取RGBA值,将彩色照变成黑白照,打马赛克等。
第一张图片是获取像素值,第二张图是变灰。
除了能操纵图片,canvas还能操纵视频,也就是<video>标签。
4)变换矩阵
CSS3中的transform有个矩阵的概念,旋转、平移、扭曲、缩放等都可以用矩阵来实现。关于CSS3的动画可以参考《CSS3中的动画效果记录》
canvas中有一个rotate()方法,实现旋转,但其实旋转的是canvas画布,并不是旋转画出来的那个图形。
如果用transform()方法的话,就可以实现旋转图形。这边有个对比实例,可以在线调试。
2D渲染的上下文矩阵如下,可以忽略最后一行:
2D渲染的坐标计算如下,关于计算过程可以研究下线性代数,简单点说就是a和x、y、1分别相乘。
rotate与skew的矩阵计算会涉及到三角函数中的正弦、余弦还有正切。
//scale()对应的矩阵 下面是CSS3中的写法,对应的方法是CanvasRenderingContext2D.transform
matrix(sx,0,0,sy,0,0);/*sx和sy分别对应X轴和Y轴的缩放比率*/ //rotate()对应的矩阵
//在JS中θ对应的是弧度转换公式为 弧度= 2 * PI / 360 * 角度
matrix(cosθ,sinθ,-sinθ,cosθ,0,0); //skew()对应的矩阵
//θy对应的是Y轴的弧度 θx对应的是X轴的弧度
matrix(1,tan(θy),tan(θx),1,0,0)
矩阵计算还会涉及到很多其他的数学知识,例如一次函数,我基本都已经忘记了,囧,都得重新查看了。
有个在线编辑matrix的网站,可以在线制作。
5)相关的计算公式
a. 三角函数基础公式
JavaScript中有两个反正切函数,Math.atan(ratio)与Math.atan2(y, x)。
第一个方法返回一个 -pi/2 到 pi/2 弧度之间的数值,第二个方法返回一个 -pi 到 pi 之间的数值。
b. 角度与弧度的互转
在JavaScript中,三角函数等用的是弧度,例如Math.sin、Math.cos等方法;旋转是用角度。所以两者之间是需要换算的。
radians是弧度,degrees是角度
c. 两点间的距离
使用了直角三角形的勾股定理。坐标轴中的P1与P2,就相当于公式中的A与B。
6)绘制文本
文本一般会设置文本内容(fillText)、尺寸字体(font),颜色(fillStyle),对齐(textAlign、textBaseline)等。
ctx.fillStyle = '#1d1d72';//字体颜色
ctx.font = size+'px serif';//字体尺寸
ctx.textBaseline = 'middle';//上下居中
ctx.textAlign = 'center';//水平居中
ctx.fillText(param.txt, width/2, height/2);
三、canvas动画
要实现动画就需要用JavaScript实现很多物理概念。
关于canvas动画可以参考两本书《HTML5 JavaScript动画基础》和《HTML5 Canvas基础教程》。pdf和源码都已经分享了出来。
1)速度向量
速度(speed)是速度向量(velocity)中的一部分,速度向量还包括方向。
用vx表示x轴上的速度向量,有vy表示y轴上的速度向量。还可以表示角度旋转,用vr表示。
vx为正数表示向右,负数表示向左。vy为正数表示向下,负数表示向上。
下图就是一个向右移动的球,vx=1,详细代码可以参考这里。
2)角速度
假设物体以1个像素的速度向45°方向移动,那么vx和vy可以通过余弦与正弦获取。
速度和方向映射成一个直角三角形。
vx = Math.cos(angle)*speed;
vy = Math.sin(angle)*speed;
上图就是经过计算后的角速度示例。
3)加速度
速度向量改变的是物体的物理位置,加速度改变的是速度向量。
下面的图片与速度向量中的gif内容是相同的,只是每次循环给vx加了0.1个值。
4)边界
处理边界,有多种选择,移除、置回边界内、屏幕环绕、反弹回边界内等。
左图是置回边界内,右图是反弹回边界内的效果。
5)摩擦力
一个比较简单的实现是,设置一个friction(摩擦力变量,一个小于1的数字),将这个数与vx和vy分别相乘,获取新的值。
这两个值会越来越小,最终停止。
除了上面几种基础的动画,还有些高级的动画,缓动、弹动、碰撞检测等。
四、canvas的优缺点
1)优点:
1. 在呈现图像、文本和动画的时候,由于 canvas 不存在与解析 HTML 和维护分层文档模型有关的开销,因此,在 canvas 中这些任务总是要比在 HTML 中快。
2. 可以实现一致的、跨平台的呈现。例如浏览器的transform属性,不同浏览器可能就需要使用自己独特的前缀。
3. 画出来的图形可以直接保存为 .png 或者 .jpg的图形。
4. 最适合于画光栅图像(如游戏和不规则几何图形等),编辑图片还有其他基于像素的图形操作。
2)缺点:
1. 由于 canvas 里面没有dom节点,当某个元素需要执行交互事件(如click)的时候只能是通过坐标来判断。
2. 没有实现动画的API,你必须依靠定时器和其他事件来更新 canvas。
3. 对文本的渲染支持是比较差,例如自动换行。canvas中也不存在超链接的概念。
4. 由于在 canvas 上以编程方式显示的文本其实就是位图,因此搜索爬行器将完全忽略文本。文本内容也无法被屏幕阅读器识别。
参考资料:
使用 HTML 标记来补充 canvas,第 2 部分: 动画和文本渲染
使用 HTML 标记来补充 canvas,第 1 部分 : 混合使用 canvas API 和 HTML/CSS 模型
让自己也能使用Canvas的更多相关文章
- html5 canvas常用api总结(三)--图像变换API
canvas的图像变换api,可以帮助我们更加方便的绘画出一些酷炫的效果,也可以用来制作动画.接下来将总结一下canvas的变换方法,文末有一个例子来更加深刻的了解和利用这几个api. 1.画布旋转a ...
- 【探索】利用 canvas 实现数据压缩
前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...
- 简单入门canvas - 通过刮奖效果来学习
一 .前言 一直在做PC端的前端开发,从互联网到行业软件.最近发现移动端已经成为前端必备技能了,真是不能停止学习.HTML5新增的一些东西,canvas是用的比较多也比较复杂的一个,简单的入门了一下, ...
- 获取Canvas当前坐标系矩阵
前言 在我的另一篇博文 Canvas坐标系转换 中,我们知道了所有的平移缩放旋转操作都会影响到画布坐标系.那在我们对画布进行了一系列操作之后,怎么再知道当前矩阵数据状态呢. 具体代码 首先请看下面的一 ...
- Canvas坐标系转换
默认坐标系与当前坐标系 canvas中的坐标是从左上角开始的,x轴沿着水平方向(按像素)向右延伸,y轴沿垂直方向向下延伸.左上角坐标为x=0,y=0的点称作原点.在默认坐标系中,每一个点的坐标都是直接 ...
- Canvas绘图之平移translate、旋转rotate、缩放scale
画布操作介绍 画布绘图的环境通过translate(),scale(),rotate(), setTransform()和transform()来改变,它们会对画布的变换矩阵产生影响. 函数 方法 描 ...
- 用html5的canvas和JavaScript创建一个绘图程序
本文将引导你使用canvas和JavaScript创建一个简单的绘图程序. 创建canvas元素 首先准备容器Canvas元素,接下来所有的事情都会在JavaScript里面. <canvas ...
- html5标签canvas函数drawImage使用方法
html5中标签canvas,函数drawImage(): 使用drawImage()方法绘制图像.绘图环境提供了该方法的三个不同版本.参数传递三种形式: drawImage(image,x,y):在 ...
- 使用 JavaScript 和 canvas 做精确的像素碰撞检测
原文地址:Pixel accurate collision detection with Javascript and Canvas 译者:nzbin 我正在开发一个需要再次使用碰撞检测的游戏.我通常 ...
- H5项目开发分享——用Canvas合成文字
以前曾用Canvas合成.裁剪.图片等<用H5中的Canvas等技术制作海报>.这次用Canvas来画文字. 下图中"老王考到驾照后"这几个字是画在Canvas上的,与 ...
随机推荐
- 在update语句中使用子查询
在update 中的 where 子句中使用子查询: UPDATE mg_page_log as a SET page_num=1 WHERE id in( SELECT id from mg_ ...
- C#按照指定长度分割中英文字符串
最近有一个需求:玩家发的不同长度文字,需要自适应行数. 初步实现想法很简单,直接获取字符数均分行数,再利用string.substring()切割即可.但是显而易见,由于一般字体下,中文显示宽度一般是 ...
- LabVIEW 吸星大法 - 看见的好东西都是我的(上篇)
前言 写了多年的LabVIEW程序,你是否面临这样的问题 总是在做一些重复的工作,感觉很没有意思: 总在不停的写代码,做类似的控件,实现相同的功能,丝毫没有成就感: 总在天加班,没有时间去提高自己; ...
- 制作dll自动注册工具
记录一个简单的dll自动注册工具制作:主要用到的是DllRegisterServer()方法,其实我们平常注册dll文件内部都会调用这个方法. 这里我就直接写在主程序里面了,需要注意的地方也直接在代码 ...
- bzoj1455: 罗马游戏 + bzoj2809: Dispatching(可并堆)
昨天看了可并堆是什么,写的是左偏树 大概就是一棵树 1.有左偏性质,即当前根到左叶子节点距离比到右叶子节点距离大 2.有堆性质,堆顶关键字比子树关键字小 合并两个堆的时候,关键字大的插入到关键字小的那 ...
- Weblogic反序列化漏洞补丁更新解决方案
Weblogic反序列化漏洞的解决方案基于网上给的方案有两种: 第一种方案如下 使用SerialKiller替换进行序列化操作的ObjectInputStream类; 在不影响业务的情况下,临时删除掉 ...
- 阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访
项目主页:http://alibaba.github.io/dubbo-doc-static/Home-zh.htm 我的博客:http://javatar.iteye.com
- 解读2015年互联网UGC内容发展态势,安全事件频发
<2015内容安全年报> 阿里移动安全 第一章 2015年内容安全形势 随着互联网业务的迅速发展,互联网上的信息内容带来了爆炸式的增长.由于缺乏对网络活动进行有效监督和管理的措施,致使互联 ...
- 全新 Mac 安装指南(通用篇)(推荐设置、软件安装、推荐软件)
注:本文将会不定期维护与更新,有需要的朋友请在 Github 上订阅该条 Issues:<全新 Mac 安装指南(通用篇)>. 在 Mac 电脑上只用 Windows 操作系统的同学请看到 ...
- 编译Android AOSP代码
下载完了源代码,终于到了编译的阶段了.这个阶段远比你想象的简单,一个make命令就可以完成源代码的编译了.参照下面的教程你就可以编译出适用于Android源代码树上的所有分支,包括master.基本的 ...