让自己也能使用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上的,与 ...
随机推荐
- android的EditText重新获取焦点问题
在android开发过程中关于EditText在setFocusable(false);后,当需要再次获得焦点输入时设置setFocusable(true);后还是无法获得焦点的问题: 解决办法: 对 ...
- CF2.D
D. Santa Claus and a Palindrome time limit per test 2 seconds memory limit per test 256 megabytes in ...
- .net 文件上传大小的设置
直接在配置文件web.config 中进行如下配置,主要需要明白的就是 配置的 单位是 Byte, 所以一定计算清楚,不然会在这里纠结很久!!! <configuration> < ...
- angurlarjs学习笔记
AngularJS 根作用域($rootScope) 所有的应用都有一个 $rootScope,它可以作用在 ng-app 指令包含的所有 HTML 元素中 $rootScope 可作用于整个应用中. ...
- 加载跨域的HTML页面AJAX
//下面是谷歌浏览器处理方式,微信端,直接使用微信链接不作处理,,火狐浏览器另行处理... 借鉴地址:http://stackoverflow.com/questions/15005500/loadi ...
- SQL Server差异备份的备份/还原原理
SQL Server差异备份的备份/还原原理 记住一点:差异备份是基于最后一次完整备份的差异,而不是基于最后一次差异的差异 备份过程: 1-完整备份之后有无对数据库做过修改,如果有,记录数据库的最 ...
- ECMAScript 6入门
预计在2014年底,ECMAScript 6将会正式发布,他的草案在13年3月份被冻结,后续提出新特性将会移至ECMASript 7中.目前还没有哪款浏览器实现了ES6的全部内容,兼容性最强的一款要数 ...
- iOS block种类和切换
block 分为三种 NSGlobalBlock,NSStackBlock, NSMallocBlock. NSGlobalBlock:类似函数,位于text段: NSStackBlock:位于栈内存 ...
- 在SqlServer2008R2中,根据分隔符把一列的值切割成多列
近期工作中,有个如上图效果的需求:将一个字段里面的值,以“,"切割成多列 通过思考.搜索,在网上找到了博主Microshaoft的文章: 妙用 T-SQL: PARSENAME 函数 (也可 ...
- 2013 duilib入门简明教程 -- VS环境配置(2)
既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错误,以及路径配置错误等等,还有人不知道SVN,然后一个个文件手动下载的. 其实吧,duili ...