学习canvas基础的总结

简单介绍canvas

<canvas><img>标签很像,可是没有src和alt属性,只有width和height属性。 css定义的尺寸与canvas的尺寸比例不一致时,会出现扭曲。css

canvas起初是空白的,要找到渲染上下文来绘制。 getContext() 该方法用来获取渲染上下文和绘制功能。web

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()
新建一条路径,生成以后,图形绘制命令被指向到路径上生成路径。
列表清空重置,从新绘制新的图形。canvas

closePath()
闭合路径以后图形绘制命令又从新指向到上下文中。
非必需,当你调用fill()函数时,全部没有闭合的形状都会自动闭合,因此你不须要调用closePath()函数。可是调用stroke()时不会自动闭合。数组

stroke()
经过线条来绘制图形。若是用线条绘制必须用closePath()来闭合曲线。缓存

fill()
经过填充路径的内容区域生成实心的图形。bash

moveTo(x, y)
将笔触移动到x,y坐标点处。dom

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的值有buttroundsquare。默认是 butt

lineJoin = type
设定线条与线条间接合处的样式。round, bevelmiter。默认是 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 必须是下面的字符串值之一:repeatrepeat-xrepeat-yno-repeat

阴影shadow

shadowOffsetX = float;
shadowOffsetY = float复制代码

shadowOffsetXshadowOffsetY 用来设定阴影在X和Y轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0。

shadowBlur = float
复制代码

shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。

shadowColor = color
复制代码

shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。

canvas填充规则:

  • nonzero:non-zero winding rule, 默认值. 填充
  • evenodd: even-odd winding rule,镂空

动画:

  1. 清空canvas:clearRect();
  2. 保存canvas状态
  3. 绘制动画图形:重绘动画帧
  4. 恢复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进行动画循环

setTimeoutsetInterval并不是是专为连续循环产生的 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.数据并不要求按照顺序处理

    根据任务总量分配:   
      根据运行时间分配:
    复制代码

以上内容均是看文档学习概括的经常使用的基础的知识点,以为有用的小伙伴点个当心心吧

相关文章
相关标签/搜索