Canvas概述
1. 与Flas的区别
Canvas 和Flash的思路完全不一样,Flash是上屏幕之后还是对象,编程语言叫做 Action Script 也是ECMAScript范畴。Canvas上屏幕之后像素化了,再也不能得到这个对象了,所以要想让这个元素运动,必须擦除整个屏幕、重绘这个元素。Canvas更流畅,手机端也嗷嗷流畅。
2. 创建Canvas画布标签
显示默认提醒消息:如果浏览器不支持Canvas,Canvas会被默认渲染为普通标签显示文字
html1
| <canvas width="200px" height="200px">对不起您的浏览器不支持画布!</canvas>
|
注意:Canvas有一个默认宽高,大概为300 x 150
,如果我们用CSS样式去设置Canvas的宽高,会导致画布扭曲,必须在Canvas标签内部,以属性的方式去添加宽高值。
3. 用Javascript操作2D画布
首先要获取到画布对象:
html1 2 3 4 5
| <canvas id="myCanvas" width="800px" height="500px">对不起您的浏览器不支持画布!</canvas>
<script> var myCanvas = document.querySelector("#myCanvas") </script>
|
获取到画布后,使用画布对象上的 .getContext()
方法新建一个画布
javascript1 2
| var ctx = myCanvas.getContext('2d');
|
之后就可以对画布进行详细的样式操作(要在绘制动作前设置样式),如设置背景颜色:
设置完样式之后就可以进行绘制操作,如绘制成一个矩形(Rect)
javascript1 2
| ctx.fillRect(100, 100, 300, 200)
|
4. API
方法:
plaintext1
| fillRect(a, b, c, d) 绘制一个填充矩形,abcd分别为四个坐标
|
属性:
笔触、填充
1. 简述
笔触也叫作“描边”,Canvas中的任何形状都是由这两个部分组成的。
笔触在canvas中视为一个“Path”的实例,必须stroke之后才能上屏幕;填充用fill才能上屏幕。
3. 绘制路径
使用 beginPath()
代表开始绘制;moveTo(x, y)
代表将笔触移动到某一坐标;lineTo(x, y)
代表直线绘制到某一点;使用 stroke()
能将绘制的图像显示出来。
如下可以绘制出一条折线:
javascript1 2 3 4 5
| ctx.beginPath(); ctx.moveTo(100, 100); ctx.lineTo(300, 300); ctx.lineTo(600, 300); ctx.stroke();
|

使用 closePath()
可以将最后一个绘制点【该绘制点是被用moveTo(x, y)
打断绘制前的那个点】与第一个绘制点连接:
javascript1 2 3 4 5 6
| ctx.beginPath(); ctx.moveTo(100, 100); ctx.lineTo(300, 300); ctx.lineTo(600, 300); + ctx.closePath(); ctx.stroke();
|

连续使用 moveTo()
可以让开始新的绘制点:
javascript1 2 3 4 5 6 7 8
| ctx.beginPath(); ctx.moveTo(100, 100); ctx.lineTo(300, 300); ctx.lineTo(600, 300);
ctx.moveTo(600, 400); ctx.lineTo(700, 400); ctx.stroke();
|

4. 绘制样式
在绘制前可以对绘制的线段进行样式设置:
javascript1 2 3 4
| ctx.lineWidth = "10"; ctx.strokeStyle = "red"; ... ... ctx.stock();
|

在绘制之后,使用 fill()
可以填充封闭图像(如果没有封闭也会自动封闭)的颜色,设置 fillStyle
属性可以来设置填充颜色:
javascript1 2 3 4
| ... ... ctx.stock(); ctx.fillStyle = "skyblue" ctx.fill();
|

使用了 fill()
之后,Canvas会自动认为之前的绘制操已经绘制了一个独立的图形。
6. 快速绘制
strokeReact(x, y, w, h)
快速绘制一个矩形
javascript1 2
| ctx.fillStyle = "lightseagreen" ctx.strokeReact(100, 100, 300, 200);
|

filRecto是一个快捷方法,让你省略了beginPath、move To、lineTo。所以fillRect(100,100,300,200)等价于:
javascript1 2 3 4 5 6
| ctx.move(100,100); ctx.lineTo(400,100); ctx.lineTo(400,300); ctx.lineTo(100,300); ctx.closePath(); ctx.fill();
|
6. 绘制复杂图像
javascript1 2 3 4 5 6 7 8
| for (var i = 0; i <= 500; i += 10) { ctx.beginPath(); ctx.moveTo(i, i); ctx.lineTo(i + 200, i); ctx.lineTo(i, i + 300); ctx.closePath(); ctx.stroke(); }
|

7. API
方法:
plaintext1 2 3 4 5 6 7 8 9
| beginPath() 代表开始绘制
moveTo(x, y) 代表将笔触移动到某一坐标
lineTo(x, y) 代表直线绘制到某一点
stroke() 能将绘制的图像显示出来
fill() 可以填充封闭图像
|
属性:
plaintext1 2 3 4 5
| lineWidth 设置绘制线的宽度
strokeStyle 设置绘制线的颜色样式
fillStyle 设置填充色的样式
|

弧
1. 绘制弧线
使用 arc(x, y, r, startRad, endRad, bollen)
绘制弧线,arc属于笔触,需要使用beginPath()
和stroke()
来设置开始与绘制动作。
javascript1 2 3
| ctx.beginPath(); ctx.arc(200, 200, 100, 0, 1, true); ctx.stroke();
|

整圆就是 ctx.arc(200, 200, 100, 0, Math.PI*2, true);
绘制笑脸的方法:
html1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <canvas id="myCanvas" width="800px" height="500px">对不起您的浏览器不支持画布!</canvas>
<script> var myCanvas = document.querySelector("#myCanvas") var ctx = myCanvas.getContext('2d'); ctx.beginPath(); ctx.arc(200, 200, 200, 0, Math.PI * 2, true); ctx.stroke();
ctx.beginPath(); ctx.arc(90, 140, 30, 0, Math.PI * 2, true); ctx.stroke();
ctx.beginPath(); ctx.arc(300, 140, 30, 0, Math.PI * 2, true); ctx.stroke();
ctx.beginPath(); ctx.arc(200, 200, 100, 0.6, 2.5, false); ctx.stroke(); </script>
|

2. API
方法:
plaintext1 2
| arc(x, y, r, startRad, endRad, bollen) 绘制弧度,xy为圆心坐标,r为绘制半径,startRad为初始角度,endRad为最终角度,bollen设置为true为逆时针绘制false为顺时针绘制
|
绘制渐变
1. 创建渐变色
使用 createLinearrGradient(x1, y1, x2, y2)
创建一个渐变对象,用 addColorStop(rate, color)
添加渐变颜色,将画布的 fillStyle
属性设置为这个渐变对象,即可以填充渐变颜色。
如绘制一个矩形,矩形内的填充色为从blue
渐变到red
javascript1 2 3 4 5 6
| var lingrad = ctx.createLinearGradient(100, 100, 400, 400); lingrad.addColorStop(0, 'red'); lingrad.addColorStop(1, 'blue');
ctx.fillStyle = lingrad; ctx.fillRect(100, 100, 300, 300);
|

2. API
方法:
plaintext1 2 3 4 5
| createLinearrGradient(x1, y1, x2, y2) 创建一个渐变对象,(x1, y1)是渐变的起始坐标,(x2, y2)是渐变的结束坐标
addColorStop(rate, color) 添加渐变颜色,rate为一个int值,初始值为0,colr为一个颜色
|
文字
1. 添加文字
使用 fillText(content, x, y)
来设置文字,注意(x, y)为文字基线的位置
javascript1
| ctx.fillText("你好", 100, 100);
|
2. 调整样式
通过 font
属性来设置字体、字号
font
的级联样式 ctx.font = "font-size font-family"
使用图片
1. 添加图片
添加一个图片首先要创建一个img
的实例,设置实例的src
,监听这个实例的load事件,当图片加载完成后,利用 drawImage(img, x, y)
绘制出图片,如下实例:
javascript1 2 3 4 5
| var img = new Image(); img.src = "images/0.jpg"; img.onload = function(){ ctx.drawImage(img, 100, 100); }
|
2. API
plaintext1 2 3 4 5
| drawImage(img, x, y, w, h) img为一个图片示例,xy为图片左上角坐标,w为图片宽度,h为图片高度
drawImage(img, X, Y, W, H, x, y, w, h) img为一个图片示例,XYWH可以设置图片的切片位置
|
运动
1. 原理
canvas中元素不能运动,因为上屏幕之后就再也得不到它了,没有任何变量可以持有。
所以必须通过重绘一个新的矩形,利用视觉暂留,形成运动。
清屏 → 更新 → 渲染 → 清屏 → 更新 → 渲染 → …
清屏:
javascript1
| ctx.clearRect(0, 0, 800, 600)
|
2. 面向对象制变成作运动函数
javascript1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function Circle(x, y, r, color) { this.x = x; this.y = y; this.r = r; this.color = color; } Circle.prototype.render = function () { ctx.beginPath(); ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true); ctx.fillStyle = this.color; ctx.fill(); } Circle.prototype.update = function () { this.x += 10; }
var yuan = new Circle(100, 100, 60, "blue");
setInterval(function () { ctx.clearRect(0, 0, 800, 600) yuan.update(); yuan.render(); }, 20)
|

3. 使用ES6来详细来面向对象编程编写动画函数
javascript1 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 39 40 41 42 43 44
| class Actor { constructor() { actorsArr.push(this); } render() { throw new Error("所有演员必须重写render函数") } update() { } }
class Circle extends Actor { constructor(x, y, r, color) { super(); this.x = x; this.y = y; this.r = r; this.color = color; } render() { ctx.beginPath(); ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true); ctx.fillStyle = this.color; ctx.fill(); } update() { this.x++; } }
var actorsArr = []
var yuan = new Circle(100, 100, 50, "red"); setInterval(() => { ctx.clearRect(0, 0, 800, 600); for (var i = 0; i < actorsArr.length; i++) { actorsArr[i].update(); actorsArr[i].render(); } }, 20);
|