简单介绍canvas
<canvas>
与<img>
标签很像,但是没有src和alt属性,只有width和height属性。 css定义的尺寸与canvas的尺寸比例不一致时,会出现扭曲。
canvas起初是空白的,要找到渲染上下文来绘制。 getContext() 该方法用来获取渲染上下文和绘制功能。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');// 需要检查支持性,是否支持canvas.getContext
复制代码
矩形
fillRect(x, y, width, height);// 填充矩形
strokeRect(x, y, width, height);//矩形边框
clearRect(x, y, width,height);// 清除指定矩形区域,清除部分为透明的
复制代码
绘制路径:
- 创建路径的起始点
- 使用画图命令,画出路径
- 路径封闭
- 路径生成,绘制图形(描边,填充)
beginPath()
新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
列表清空重置,重新绘制新的图形。
closePath()
闭合路径之后图形绘制命令又重新指向到上下文中。
非必需,当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
stroke()
通过线条来绘制图形。如果用线条绘制必须用closePath()来闭合曲线。
fill()
通过填充路径的内容区域生成实心的图形。
moveTo(x, y)
将笔触移动到x,y坐标点处。
lineTo(x, y)
绘制直线。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
圆心坐标,半径,起始角度,结束角度,false顺时针,true逆时针。
三点钟方向为0°(弧度),弧度=(Math.PI/180)*角度。
arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
rect(x, y, width, height)
绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。笔触自动置回(0,0)。
quadraticCurveTo(cp1x, cp1y, x,y)
绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。蓝色是起始点和结束点,红色是控制点。
path2D对象:用来缓存和记录绘画命令,可快速回顾绘制路径。
Path2D()
会返回一个新初始化的Path2D对象(可能将某一个路径作为变量——创建一个它的副本,或者将一个包含SVG path数据的字符串作为变量)。
new Path2D(); // 空的Path对象
new Path2D(path); // 克隆Path对象
new Path2D(d); // 从SVG建立Path对象
Path2D.addPath(path [, transform]);// 添加了一条路径到当前路径(可能添加了一个变换矩阵)。
复制代码
新的Path2D API有另一个强大的特点,就是使用SVG path data来初始化canvas上的路径。这将使你获取路径时可以以SVG或canvas的方式来重用它们。
var p = new Path2D("M10 10 h 1 80 v 80 h -80 Z");// 将先移动到点 (M10 10) 然后再水平移动80个单位(h 80),然后下移80个单位 (v80),接着左移80个单位 (h -80),再回到起点处 ( z)。
复制代码
透明度:TransparencyValue
globalAlpha = transparencyValue;// 有效值(0.0~1.0),完全透明~完全不透明
复制代码
线性样式
lineWidth = value
设置线条宽度。属性值必须为正数。默认值是1.0。
lineCap = type
设置线条末端样式。type
的值有butt
,round
和 square
。默认是 butt
。
lineJoin = type
设定线条与线条间接合处的样式。round
, bevel
和miter
。默认是 miter
。
miterLimit = value
限制当两条线相交时交接处最大长度。
所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
getLineDash()
返回一个包含当前虚线样式,长度为非负偶数的数组。
setLineDash(segments)
设置当前虚线样式。
lineDashOffset = value
设置虚线样式的起始偏移量。
用 setLineDash
方法和 lineDashOffset
属性来制定虚线样式。setLineDash
方法接受一个数组,来指定线段与间隙的交替;lineDashOffset
属性设置起始偏移量。
渐变:以用线性或者径向的渐变来填充或描边
新建一个 canvasGradient 对象,并且赋给图形的 fillStyle 或 strokeStyle 属性。
createLinearGradient(x1, y1, x2, y2)createLinearGradient
方法接受 4 个参数,表示渐变的起点 (x1,y1)
与终点 (x2,y2)
。
createRadialGradient(x1, y1, r1, x2, y2, r2)createRadialGradient
方法接受 6 个参数,前三个定义一个以 (x1,y1)
为原点,半径为 r1 的圆,后三个参数则定义另一个以(x2,y2)
为原点,半径为 r2 的圆。
gradient.addColorStop(position, color)addColorStop
方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。
图案样式patterns
createPattern(image, type)
该方法接受两个参数。Image
可以是一个 Image
对象的引用,或者另一个 canvas
对象。Type
必须是下面的字符串值之一:repeat
,repeat-x
,repeat-y
和 no-repeat
。
阴影shadow
shadowOffsetX = float;
shadowOffsetY = float;
复制代码
shadowOffsetX
和 shadowOffsetY
用来设定阴影在X和Y轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。
shadowBlur = float
复制代码
shadowBlur
用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。
shadowColor = color
复制代码
shadowColor
是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
canvas填充规则:
nonzero
:non-zero winding rule, 默认值. 填充evenodd
: even-odd winding rule,镂空
动画:
- 清空canvas:clearRect();
- 保存canvas状态
- 绘制动画图形:重绘动画帧
- 恢复canvas状态:如果已经保存了 canvas的状态,可以先恢复它,然后重绘下一帧。
你可以使用setInterval()
方法,它就可以定期执行指定代码。如果我们需要做一个游戏,我们可以使用键盘或者鼠标事件配合上setTimeout()
方法来实现。通过设置事件监听,我们可以捕捉用户的交互,并执行相应的动作。 采用window.requestAnimationFrame()
实现动画效果。这个方法提供了更加平缓并更加有效率的方式来执行动画,当系统准备好了重绘条件的时候,才调用绘制动画帧。一般每秒钟回调函数执行60次,也有可能会被降低。
变形transformations:
save()
和 restore()
: save 和 restore 方法是用来保存和恢复 canvas 状态的,canvas的状态保存在栈中。tanslate(x, y)
; 左右,上下平移。rotate
旋转。scale
缩放。transform(m11, m12, m21, m22, dx, dy)
这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵,在这里我们用下面的矩阵
m11 m21 dx
m12 m22 dy
0 0 1
复制代码
m11:水平方向的缩放
m12:水平方向的倾斜偏移
m21:竖直方向的倾斜偏移
m22:竖直方向的缩放
dx:水平方向的移动
dy:竖直方向的移动
复制代码
setTransform(m11, m12, m21, m22, dx, dy)
resetTransform()
复制代码
canvas优化
使用requestAnimationFrame
进行动画循环
setTimeout
和 setInterva
l并非是专为连续循环产生的 API,所以可能无法达到流畅的动画表现,故用 requestAnimationFrame
,可能需要polyfill
const raf = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.oRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(callback) {
window.setTimeout(callback, 1000 / 60)
}
复制代码
利用剪辑区域来处理动画背景或其他不变的图像
背景比较复杂可以使用剪辑区域技术,通过每帧较少的绘制来获得较好的性能。
利用剪辑区域技术来恢复上一帧动画所占背景图的执行步骤:
- 调用 context.save(),保存屏幕 canvas的状态
- 通过调用 beginPath来开始一段新的路径
- 在 context对象上调用 arc()、rect()等方法来设置路径
- 调用 context.clip()方法,将当前路径设置为屏幕 canvas的剪辑区域
- 擦除屏幕 canvas中的图像(实际上只会擦除剪辑区域所在的这一块范围)
- 将背景图像绘制到屏幕canvas上(绘制操作实际上只会影响剪辑区域所在的范围,所以每帧绘制图像像素数更少)
- 恢复屏幕 canvas的状态参数,重置剪辑区域
离屏缓冲区(离屏canvas)
先绘制到一个离屏 canvas
中,然后再通过 drawImage
把离屏 canvas
画到主 canvas
中,就是把离屏 canvas
当成一个缓存区。把需要重复绘制的画面数据进行缓存起来,减少调用 canvas
的 API的消耗。
const cacheCanvas = document.createElement('canvas')
const cacheCtx = cacheCanvas.getContext('2d')
cacheCtx.width = 200
cacheCtx.height = 200
// 绘制到主canvas上
ctx.drawImage(0, 0)
复制代码
必要时,可以使用多个离屏 canvas
另外,离屏canvas
不再使用时,最好把手动将引用重置为 null
,避免因为 js和dom之间存在的关联,导致垃圾回收机制无法正常工作,占用资源。
尽量利用CSS
尽量少的调用 canvas API
相比于正常的js操作,频繁的调用canvasAPI更加消耗资源。
避免阻塞
在进行某些耗时操作,例如计算大量数据,一帧中包含了太多的绘制状态,大规模的 DOM操作等,可能会导致页面卡顿,影响用户体验,可以通过以下两种手段:
-
web worker
web worker
最常用的场景就是大量的频繁计算,减轻主线程压力,如果遇到大规模的计算,可以通过此 API分担主线程压力,此 API兼容性已经很不错了,既然canvas
可以用,那web worker
也就完全可以考虑使用。 -
分解任务
满足:
1.循环处理操作并不要求同步
2.数据并不要求按照顺序处理根据任务总量分配: 根据运行时间分配: 复制代码
以上内容均是看文档学习归纳的常用的基础的知识点,觉得有用的小伙伴点个小心心吧