让自己也能使用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上的,与 ...
随机推荐
- CSS中"!important"的使用
本篇文章使用最新的IE10以及firefox与chrome测试(截止2013年5月27日22:23:22) CSS的原理: 我们知道,CSS写在不同的地方有不同的优先级, .css文件中的定义 < ...
- 解决 adb.exe 停止工作小续
继adb 停止工作的问题之后,又碰见了adb 停止工作的问题. 在使用adb install app.apk 之后给出错误信息如下: * daemon not running. starting it ...
- Python实战 :2017国考职业表excel转数据库,再查询生成excel
最近看2017年国考的职业表,多而杂,不好过滤我想要的信息,特此把它转成Sqlite3数据库,再从数据库里把查询结果导出成excel,方便找职业. (后附上整套代码) 环境:python2.7 x ...
- 利用sqlmap进行mysql提权的小方法(win与liunx通用)
文章作者:pt007@vip.sina.com文章来源:https://www.t00ls.net/thread-36196-1-1.html1.连接mysql数据打开一个交互shell:sqlmap ...
- Nginx 配置从零开始
作为一个 nginx 的初学者记录一下从零起步的点滴. 基本概念 Nginx 最常的用途是提供反向代理服务,那么什么反向代理呢?正向代理相信很多大陆同胞都在这片神奇的土地上用过了,原理大致如下图: 代 ...
- shell脚本删除指定mobileprovision
由于某种原因,xcode帮我按照了几千个开发和上线证书,需要删除这部分证书: #dir="/Users/Ethan/Library/MobileDevice/Provisioning Pro ...
- 解读ASP.NET 5 & MVC6系列(6):Middleware详解
在第1章项目结构分析中,我们提到Startup.cs作为整个程序的入口点,等同于传统的Global.asax文件,即:用于初始化系统级的信息(例如,MVC中的路由配置).本章我们就来一一分析,在这里如 ...
- Some practices to write better C#/.NET code(译)
C#(.NET)中有关编码的一些建议,原文地址:http://www.codeproject.com/Articles/539179/Some-practices-to-write-better-Cs ...
- 扩展Bootstrap Tooltip插件使其可交互
最近在公司某项目开发中遇见一特殊需求,请笔者帮助,因此有了本文的插件.在前端开发中tooltip是一个极其常用的插件,它能更好向使用者展示更多的文档等帮助信息.它们通常都是一些静态文本信息.但同事他们 ...
- Google分布式构建软件之四:分发构建结果
注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 之前的文章,介绍了Google在分布式构建软件过程中,如何把构建过程分发到许 ...