canvas 笔记
canvas教程
一. 概述
长久以来,web上的动画都是Flash。比如动画广告、游戏等等,基本上都是F1ash实现的。Flash是有缺点的,比如需要安装 Adobe Flash Player,漏洞多,重量比较大。卡顿和不流畅等等
1.1 简介
HTML5提出了一个新的 canvas标签,彻底颠覆了Flash的主导地位。无论是广告、游戏都可以使用 canvas实现了, Canvas是一个轻量级的画布,我们使用 Canvas进行 JavaScript的编程,不需要增加额外的插件,性能也很好,不卡顿,在手机中也很流畅
二. 基本使用
1 2 3
| <canvas width="400" height="500" id="mycanvas"> 当前浏览器版本不支持,请升级浏览器 </canvas>
|
canvas的标签属性只有两个, width和 height.。表示的是 canvas画布的宽度和高度。注意 canvas的 width和 height不要用css的样式来设置,如果使用css的样式来设置,画布会失真,会变形 标签对儿里面的文字是用来提示低版本浏览器(IE6/7/8)
方法/属性 |
描述 |
getContext() |
得到画布上下文,上下文有两个,2d的上下文和3d的上下文 |
fillStyle |
设置颜色 |
fillRect(x,y,width,height) |
方法绘制“已填色”的矩形。默认的填充颜色是黑色。 |
三.canvas的编程思想
3.1 像素化
我们使用 canvas绘制了一个图形,一旦绘制成功了, canvas就像素化了他们。 canvas没有能力,从画布上再次得到这个图形,也就是说我们没有能力去修改已经在画布上的内容。这个就是 canvas比较轻量的原因,Flash重的原因之一就有它可以通过对应的api得到已经上“画布”的内容然后再次绘制,如果我们想要让这个 canvas图形移动,必须按照清屏-更新-渲染的逻辑进行编程,总之就是重新再画一次
3.2 动画思想
清屏-更新-渲染,这个思想就可以为 canvas的动画思想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var canvas=document.getElementById("mycanvas"); var ctx=canvas.getContext("2d") ctx.fillStyle="blue"
var left=10; setInterval(()=>{ ctx.clearRect(0,0,700,600) left++; ctx.fillRect(left,left,100,100) if(left==700){ left=10 } },4)
|
实际上,动画的生存就是相关静态画面连续插放了,这个就是动画的过程。我们把每一次绘制的静态画面叫做 " 一帧 ",时间的间隔(定时器的间隔)就表示的是帧的间隔
3.3 面向对象实现 canvas 动画
因为 canvas不能得到已经上屏的对象,所以我们要维持对象的状态。在 canvas动画中,我们都使用面向对象来进行编程,因为我们可以使用面向对象的方式来维持 canvas需要的属性和状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| var can = document.getElementById("can") var ctx = can.getContext("2d");
function Rect(x, y, w, h, color) { this.x = x; this.y = y; this.w = w; this.h = h; this.color = color }
Rect.prototype.update = function () { this.x++; }
Rect.prototype.render = function () { ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.w, this.h); }
var r1 = new Rect(100, 100, 50, 50, "#91d5ff")
setInterval(() => { ctx.clearRect(0, 0, can.width, can.height) r1.update() r1.render() }, 5)
|
动画过程在主定时器里面,每一帧都会调动实例的更新和渲染方法
四. canvas绘制功能
方法/属性 |
描述 |
fillStyle |
设置填充颜色 |
fillRect(x,y,width,height) |
方法绘制“已填色”的矩形。默认的填充颜色是黑色。 |
strokeStyle |
设置边框颜色 |
strokeRect(x,y,width,height) |
方法绘制矩形边框。默认的填充颜色是黑色。 |
clearRect(x,y,width,height) |
清除画布内容 |
globalAlpha |
设置透明度 0-1 |
4.1 绘制路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ctx.beginPath()
ctx.moveTo(100,100)
ctx.lineTo(200,300); ctx.lineTo(300,230); ctx.lineTo(440,290); ctx.lineTo(380,50);
ctx.closePath()
ctx.strokeStyle="#91d5ff"
ctx.stroke()
ctx.fill()
|

4.2 绘制圆弧
1
| arc(x, y, radius, startAngle, endAngle, anticlockwise)
|
x,y
为绘制圆弧所在圆上的圆心坐标。
radius
为半径。
startAngle
以及endAngle
参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准。
- 参数
anticlockwise
为一个布尔值。为true时,是逆时针方向,否则顺时针方向。
注意:arc()
函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:
弧度=(Math.PI/180)*角度。
1 2 3 4 5 6 7
| ctx.beginPath();
ctx.arc(200,200,100,0,2*Math.PI,false)
ctx.stroke()
|
canvas实现鼠标跟随炫彩小球
canvas实现炫彩小球弹弹
4.3 线型
我们可以利用lineWidth
设置线的粗细,属性值必须是数字,默认是1.0。没有单位
1 2 3 4 5 6
| ctx.beginPath(); ctx.moveTo(100,150) ctx.lineTo(200,200) ctx.lineTo(300,50) ctx.lineWidth=10 ctx.stroke()
|
线型教程
4.4 文本
1 2 3 4 5
| ctx.font="30px 宋体"
ctx.textAlign="start" ctx.fillText("Hello Canvas",100,100)
|
4.5 渐变
1 2 3 4 5 6 7 8
| var linear=ctx.createLinearGradient(0, 0, 200, 200); linear.addColorStop(0,"red"); linear.addColorStop(0.5,"#91d5ff"); linear.addColorStop(0.8,"#ffec3d"); linear.addColorStop(1,"blue") ctx.fillStyle=linear ctx.fillRect(10,10,200,100)
|
4.6 阴影
1 2 3 4 5 6 7 8
| ctx.shadowOffsetX=10 ctx.shadowOffsetY=10 ctx.shadowBlur=3; ctx.shadowColor="red";
ctx.font="30px 宋体" ctx.fillText("Hello Canvas",100,100)
|
五. 图片使用
1 2 3 4 5 6 7 8
| var img=new Image();
img.src="https://tva3.sinaimg.cn/large/006djwNZgy1gmqxcekdm8j31hc0u0dln.jpg"
img.onload=function(){ ctx.drawImage(img,100,100,200,100) }
|
1
| drawImage(img,x,y,width,height)
|

1
| drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
- 前4个参数指的是你在图片中设置切片的宽度和高度,以及切片位置
- 后4个参数指的是切片在画布上的位置和切片的宽度和高度
六.资源管理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| function Game() { this.dom = document.querySelector("canvas"); this.ctx = this.dom.getContext("2d");
this.R = { "01": "https://tvax3.sinaimg.cn/large/006djwNZgy1gkyvxt1exaj33y8280b2c.jpg", "02": "https://tva1.sinaimg.cn/large/006djwNZgy1gkyzq80yobj31hc0u0n4r.jpg", "03": "https://tva3.sinaimg.cn/large/006djwNZgy1gmqxcekdm8j31hc0u0dln.jpg", "04": "https://tva4.sinaimg.cn/large/006djwNZgy1gmqxee8qo6j31hc0u0qcr.jpg" } var allAmount = Object.keys(this.R).length var count = 0 for (k in this.R) { var src = this.R[k] this.R[k] = new Image() this.R[k].src = src; var self = this this.R[k].onload = function () { count++; self.ctx.clearRect(0, 0, 600, 500) self.ctx.font = "16px Arial" self.ctx.fillText("图片已加载:" + count + "/" + allAmount, 10, 50) } }
} console.log(new Game());
|
七.变形
7.1 概述
save()
保存画布(canvas)的所有状态
restore()
save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
Canvas状态存储在栈中,每当save()
方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:
- 当前应用的变形(即移动,旋转和缩放,见下)
- 以及下面这些属性:
strokeStyle
, fillStyle
, globalAlpha
, lineWidth
, lineCap
, lineJoin
, miterLimit
, lineDashOffset
, shadowOffsetX
, shadowOffsetY
, shadowBlur
, shadowColor
, globalCompositeOperation
, font
, textAlign
, textBaseline
, direction
, imageSmoothingEnabled
你可以调用任意多次 save
方法。每一次调用 restore
方法,上一个保存的状态就从栈中弹出,所有设定都恢复。
7.2 translate
- translate和CSS3的 translate属性一样也是发挥着空间平移作用
1 2 3 4 5 6 7 8
| ctx.save(); ctx.translate(50,50) ctx.fillRect(0,0,120,120)
ctx.restore()
ctx.fillRect(0,200,120,120)
|
- 变形实际上都是将整个画布进行的变形,所以如果一旦变形操作多了,画布将变得不可控
- 如果使用到变形,一定记住下面的规律:变形之前要先备份,将世界和平的状态进行备份,然后再变形,变形完毕后一定要恢复到世界和平的样子,不要影响下一次的操作
7.3 rotate
1 2 3 4 5 6 7 8 9
| ctx.save(); ctx.translate(200,100) ctx.rotate(1) ctx.fillRect(0,0,120,120)
ctx.restore()
ctx.fillRect(0,200,120,120)
|
rotate(angle)
这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate
方法。
7.4 scale
1 2 3 4 5 6 7 8
| ctx.save(); ctx.translate(200,100) ctx.scale(0.6,0.6) ctx.fillRect(0,0,120,120)
ctx.restore()
ctx.fillRect(0,200,120,120)
|
scale
方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比1小,会缩小图形, 如果比1大会放大图形。默认值为1, 为实际大小。
最后一个方法允许对变形矩阵直接修改。
1 2
| transform(a, b, c, d, e, f)
|
这个函数的参数各自代表如下:
a(m11)
水平方向的缩放
b(m12)
竖直方向的倾斜偏移
c(m21)
水平方向的倾斜偏移
d(m22)
竖直方向的缩放
e(dx)
水平方向的移动
f(dy)
竖直方向的移动
八.合成
- 合成其实就是我们常见的蒙板状态,本质就是如何进行压盖,如何进行显示
1 2 3 4 5 6
| ctx.fillStyle="#91d5ff" ctx.fillRect(100,100,100,100) ctx.fillStyle="#ffc069" ctx.beginPath() ctx.arc(200,200,60,0,7,false) ctx.fill()
|
1
| ctx.globalCompositeOperation="destination-over"
|