Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Canvas文档 #39

Open
Marinerer opened this issue Mar 25, 2021 · 4 comments
Open

Canvas文档 #39

Marinerer opened this issue Mar 25, 2021 · 4 comments

Comments

@Marinerer
Copy link
Owner

Marinerer commented Mar 25, 2021

目录


系列教程

@Marinerer
Copy link
Owner Author

Marinerer commented Mar 25, 2021

js文档:https://www.canvasapi.cn/
教程:https://wangdoc.com/webapi/canvas.html
参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial
示例:https://www.twle.cn/l/yufei/canvas/canvas-basic-index.html
MDN: CanvasRenderingContext2D API接口参考
贝塞尔曲线 - 维基百科

canvas 文档

目录

    1. 绘制形状
    • 路径
      • 线型
      • 弧线
      • 贝塞尔曲线
      • 椭圆
      • Path2D 对象
    • 矩形
    • 文本
    • 渐变和图案填充
    • 阴影
    • 透明度
    • 合成与裁剪
    • 状态的保存和恢复
    • 其他属性和方法
    1. 图像变换
    • 旋转
    • 缩放
    • 位移
    • 矩阵
  • 图像处理
    • 绘制图片
    • 像素读写
    1. 动画
    1. canvas元素方法
    • Canvas.getContext()
    • Canvas.toDataURL()
    • Canvas.toBlob()

1. 绘制形状

Canvas 画布提供了一个作图的平面空间,该空间的每个点都有自己的坐标。原点(0, 0)位于图像左上角,x轴的正向是原点向右,y轴的正向是原点向下。

路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。

  1. 首先,你需要创建路径起始点。
  2. 然后你使用画图命令去画出路径。
  3. 之后你把路径封闭。
  4. 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

以下方法和属性用来绘制路径:

  • beginPath():开始绘制路径。
  • closePath():结束路径,返回到当前路径的起始点,会从当前点到起始点绘制一条直线。如果图形已经封闭,或者只有一个点,那么此方法不会产生任何效果。
  • moveTo(x, y):设置路径的起点,即将一个新路径的起始点移动到(x,y)坐标。
  • fill():在路径内部填充颜色(默认为黑色)。
  • stroke():路径线条着色(默认为黑色)。
  • fillStyle:指定路径填充的颜色和样式(默认为黑色)。
  • strokeStyle:指定路径线条的颜色和样式(默认为黑色)。
function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');
		// 笑脸
    ctx.beginPath();
    ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // 绘制外圆
    ctx.moveTo(110, 75);
    ctx.arc(75, 75, 35, 0, Math.PI, false);   // 口(顺时针)
    ctx.moveTo(65, 65);
    ctx.arc(60, 65, 5, 0, Math.PI * 2, true);  // 左眼
    ctx.moveTo(95, 65);
    ctx.arc(90, 65, 5, 0, Math.PI * 2, true);  // 右眼
    ctx.strokeStyle = "blue"
    ctx.stroke();
    
    // 扇形
    ctx.beginPath();
    ctx.moveTo(83, 102);
    ctx.bezierCurveTo(83, 94, 89, 88, 97, 88); // 左上1/4圆
    ctx.bezierCurveTo(105, 88, 111, 94, 111, 102); // 右上1/4圆
    ctx.lineTo(97, 116);
    ctx.lineTo(83, 102);
    ctx.strokeStyle = 'red'
    ctx.stroke();
  }
}

线型

lineTo() 绘制直线.

  • lineTo(x, y):使用直线从当前点连接到(x, y)坐标。

线形的控制属性

  • lineWidth:指定线条的宽度,默认为1.0。
  • lineCap:指定线条末端的样式,有三个可能的值:butt(默认值,末端为矩形)、round(末端为圆形)、square(末端为突出的矩形,矩形宽度不变,高度为线条宽度的一半)。
  • lineJoin:指定线段交点的样式,有三个可能的值:round(交点为扇形)、bevel(交点为三角形底边)、miter(默认值,交点为菱形)。
  • miterLimit:指定交点菱形的长度,默认为10。该属性只在lineJoin属性的值等于miter时有效。
  • getLineDash():返回一个数组,表示虚线里面线段和间距的长度。
  • setLineDash(segments):数组,用于指定虚线里面线段和间距的长度。
  • lineDashOffset : 设置虚线样式的起始偏移量。

弧线

  • arc():通过指定圆心和半径绘制弧形,主要用来绘制圆形或扇形
  • arcTo():通过指定两根切线和半径绘制弧形,主要用来绘制圆弧
context.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);
// `x, y`: 圆弧对应的圆心横坐标
// `radius`: 圆弧的半径大小。
// `startAngle`: 圆弧开始的角度,单位是弧度。
// `endAngle`: 圆弧结束的角度,单位是弧度。
// `anticlockwise`: 画图时应该逆时针画(true)还是顺时针画(false),这个参数用来控制扇形的方向(比如上半圆还是下半圆)。

context.arcTo(x1, y1, x2, y2, radius)
// `x1, y1`: 是第1个控制点的横坐标;
// `x2, y2`: 是第2个控制点的横坐标;
// `radius`: 是圆弧的半径大小。

注意:arc()函数中表示角的单位是弧度,不是角度。
角度与弧度的js表达式:弧度=(Math.PI/180)*角度。
比如:ctx.arc(60, 60, 50, 0, Math.PI * 2, true) 绘制了一个半径50,起始角度为0,终止角度为 2 * PI 的完整的圆。

贝塞尔曲线

  • quadraticCurveTo(cp1x, cp1y, x, y) :绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) :绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。

cubic-bezier

贝塞尔曲线 - 维基百科

椭圆

ellipse() 是 Canvas 2D API 添加椭圆路径的方法。椭圆的圆心在(x,y)位置,半径分别是radiusXradiusY ,按照anticlockwise(默认顺时针)指定的方向,从 startAngle 开始绘制,到 endAngle 结束。

ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
// `x, y`: 椭圆圆心的坐标
// `radiusX`: 椭圆长轴的半径
// `radiusY`: 椭圆短轴的半径
// `rotation, startAngle`: 椭圆将要绘制的起始点和结束点角度,以弧度表示(非角度度数)。
// `anticlockwise`: 如果为 true,逆时针方向绘制椭圆 (逆时针), 反之顺时针方向绘制。

// Demo
ctx.ellipse(100, 100, 50, 75, 45 * Math.PI/180, 0, 2 * Math.PI); //倾斜45°角

Path2D 对象

正如我们所讲,你可以使用一系列的路径和绘画命令来把对象“画”在画布上。为了简化代码和提高性能,Path2D对象已可以在较新版本的浏览器中使用,用来缓存或记录绘画命令,这样你将能快速地回顾路径。

所有的路径方法比如moveTo, rect, arcquadraticCurveTo等,如我们前面见过的,都可以在Path2D中使用。Path2D还有另一个强大的特点,就是使用SVG path data来初始化canvas上的路径。这将使你获取路径时可以以SVG或canvas的方式来重用它们。

const square = new Path2D("M10 10 h 80 v 80 h -80 Z")
ctx.stroke(square)

矩形

以下方法用来绘制矩形:

  • rect(x, y, width, height):绘制矩形路径。
  • fillRect(x, y, width, height):填充一个矩形。
  • strokeRect(x, y, width, height):绘制矩形边框。
  • clearRect(x, y, width, height):指定矩形区域的像素都变成透明,并擦除之前绘制的所有内容。

上面四个方法的格式都一样,都接受四个参数,分别是矩形左上角的横坐标和纵坐标、矩形的宽和高。

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

// line画矩形路径,填充
ctx.moveTo(10, 100)
ctx.lineTo(60, 100)
ctx.lineTo(60, 150)
ctx.lineTo(10, 150)
ctx.fillStyle = 'pink'
ctx.fill()

// rect画矩形路径,填充
ctx.beginPath()
ctx.rect(10, 10, 50, 50)
ctx.fillStyle = 'blue'
ctx.fill()

// fillRect 画矩形
ctx.fillStyle = 'green'
ctx.fillRect(80, 10, 50, 50)

// strokeRect 矩形描边
ctx.strokeStyle = 'red'
ctx.strokeRect(150, 10, 50, 50)

// clearRect 清除矩形区域内容
ctx.clearRect(40, 30, 60, 20)

文本

canvas 提供了fillText()strokeText()两种方法来渲染文本。

  • fillText(text, x, y [, maxWidth]):在指定位置绘制实心字符。
  • strokeText(text, x, y [, maxWidth]):在指定位置绘制空心字符。
  • measureText():预测量文本宽度,返回一个 TextMetrics 对象。

文本样式属性:

  • font:指定字型大小和字体,默认值为10px sans-serif
  • textAlign:文本的对齐方式,默认值为start。[start, end, left, right, center]
  • direction:文本的方向,默认值为inherit。[ltr, rtl, inherit]
  • textBaseline:文本的垂直位置,默认值为alphabetic。[top, hanging, middle, alphabetic, ideographic, bottom]

渐变和图案填充

  • createLinearGradient():定义线性渐变样式。
  • createRadialGradient():定义辐射渐变样式。
  • createPattern():使用指定的图片创建图案,通过 repetition 变量指定的方向上重复源图片。

线性渐变

ctx.createLinearGradient(x0, y0, x1, y1)

x0y0是起点的横坐标和纵坐标,x1y1是终点的横坐标和纵坐标。通过不同的坐标值,可以生成从上至下、从左到右的渐变等等。

该方法的返回值是一个CanvasGradient对象,该对象只有一个addColorStop()方向,用来指定渐变点的颜色。addColorStop()方法接受两个参数,第一个参数是0到1之间的一个位置量,0表示起点,1表示终点,第二个参数是一个字符串,表示 CSS 颜色。

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

var gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, 'green');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

辐射渐变

createRadialGradient()方法定义一个辐射渐变,需要指定两个圆。

ctx.createRadialGradient(x0, y0, r0, x1, y1, r1)

x0y0是辐射起始的圆的圆心坐标,r0是起始圆的半径,x1y1是辐射终止的圆的圆心坐标,r1是终止圆的半径。

图像填充

createPattern()方法定义一个图像填充样式,在指定方向上不断重复该图像,填充指定的区域。

ctx.createPattern(image, repetition)

该方法接受两个参数,第一个参数是图像数据,它可以是<img>元素,也可以是另一个<canvas>元素,或者一个表示图像的 Blob 对象。第二个参数是一个字符串,有四个可能的值,分别是repeat(双向重复)、repeat-x(水平重复)、repeat-y(垂直重复)、no-repeat(不重复)。如果第二个参数是空字符串或null,则等同于null

该方法的返回值是一个CanvasPattern对象。

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = 'https://example.com/pattern.png';
img.onload = function( ) {
  var pattern = ctx.createPattern(img, 'repeat');
  ctx.fillStyle = pattern;
  ctx.fillRect(0, 0, 400, 400);
};

阴影

  • CanvasRenderingContext2D.shadowBlur:阴影的模糊程度,默认为0
  • CanvasRenderingContext2D.shadowColor:阴影的颜色,默认为black
  • CanvasRenderingContext2D.shadowOffsetX:阴影的水平位移,默认为0
  • CanvasRenderingContext2D.shadowOffsetY:阴影的垂直位移,默认为0

透明度

通过设置 globalAlpha 属性或者使用一个半透明颜色作为轮廓或填充的样式。

globalAlpha 属性在需要绘制大量拥有相同透明度的图形时候相当高效。不过 strokeStylefillStyle 属性接受符合 CSS 3 规范的颜色值,那可以使用 rgba(255,0,0,0.5)来设置具有透明度的颜色。

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  // 画背景框
  ctx.fillStyle = '#6C0';
  ctx.fillRect(0, 0, 150, 75);
  ctx.fillStyle = 'rgba(0, 153, 255, 0.8)';
  ctx.fillRect(0, 75, 150, 75);

  // 设置透明度值
  ctx.globalAlpha = 0.2;

  // 画半透明圆
  ctx.fillStyle = '#FFF'
  for (var i=0;i<7;i++){
      ctx.beginPath();
      ctx.arc(75,75,10+10*i,0,Math.PI*2,true);
      ctx.fill();
  }
}

合成与裁剪

合成 globalCompositeOperation

我们不仅可以在已有图形后面再画新图形,还可以用来遮盖指定区域,清除画布中的某些部分(清除区域不仅限于矩形,像clearRect()方法做的那样)以及更多其他操作。

  • globalCompositeOperation = type : 设定了在画新图形时采用的遮盖策略,其值是一个标识12种遮盖方式的字符串。

    • source-over:默认设置,在现有画布上下文之上绘制新图形。
    • source-in:新图形只在新图形和目标画布重叠的地方绘制。其他的都是透明的。
    • source-out:在不与现有画布内容重叠的地方绘制新图形。
    • source-atop:新图形只在与现有画布内容重叠的地方绘制。
    • destination-over:在现有的画布内容后面绘制新的图形。
    • destination-in:现有的画布内容保持在新图形和现有画布内容重叠的位置。其他的都是透明的。
    • destination-out:现有内容保持在新图形不重叠的地方。
    • destination-atop:现有的画布只保留与新图形重叠的部分,新的图形是在画布内容后面绘制的。
    • lighter:两个重叠图形的颜色是通过颜色值相加来确定的。
    • copy:只显示新图形。
    • xor:图像中,那些重叠和正常绘制之外的其他地方是透明的。
    • multiply:将顶层像素与底层相应像素相乘,结果是一幅更黑暗的图片。
    • screen:像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。
    • overlay:multiply和screen的结合,原本暗的地方更暗,原本亮的地方更亮。
    • darken:保留两个图层中最暗的像素。
    • lighten:保留两个图层中最亮的像素。
    • color-dodge:将底层除以顶层的反置。
    • color-burn:将反置的底层除以顶层,然后将结果反过来。
    • hard-light:屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。
    • soft-light:用顶层减去底层或者相反来得到一个正值。
    • difference:一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。
    • exclusion:和difference相似,但对比度较低。
    • hue:保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。
    • saturation:保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)。
    • color:保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)。
    • luminosity:保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)。

裁剪路径 clip

裁切路径和普通的 canvas 图形差不多,不同的是它的作用是遮罩,用来隐藏不需要的部分。

  • clip() :将当前正在构建的路径转换为当前的裁剪路径。
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

ctx.beginPath();
ctx.arc(0,0,60,0,Math.PI*2,true);
ctx.clip(); // 创建一个扇形的裁剪区域

// draw background
var lingrad = ctx.createLinearGradient(0,0,0,150);
lingrad.addColorStop(0, 'blue');
lingrad.addColorStop(1, 'red');
ctx.fillStyle = lingrad;
ctx.fillRect(0,0,150,150);

状态的保存和恢复

  • save() :将画布的当前样式保存到堆栈,相当于在内存之中产生一个样式快照。
  • restore() :将画布的样式恢复到上一个保存的快照,如果没有已保存的快照,则不产生任何效果。

Canvas状态存储在栈中,每当save()方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:

  • 当前的变形矩阵
  • 当前的剪切区域
  • 当前的虚线列表
  • 以下属性当前的值:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled

可以调用任意多次 save方法。每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

ctx.fillRect(0,0,300,300);
ctx.save();   // 保存默认状态

ctx.fillStyle = 'blue'    // 蓝色状态
ctx.fillRect(25,25,250,250);

ctx.save(); // 保存当前状态
ctx.fillStyle = 'red'     // 红色状态
ctx.fillRect(50,50,200,200);

ctx.restore(); // 恢复至蓝色状态
ctx.fillRect(75,75,150,150)

ctx.restore(); // 恢复至默认状态
ctx.fillRect(100,100,100,100)

其他属性和方法

2. 图像变换

以下方法用于图像变换。

  • CanvasRenderingContext2D.rotate():图像旋转
  • CanvasRenderingContext2D.scale():图像缩放
  • CanvasRenderingContext2D.translate():图像平移
  • CanvasRenderingContext2D.transform():通过一个变换矩阵完成图像变换
  • CanvasRenderingContext2D.setTransform():取消前面的图像变换

旋转

顺时针旋转的弧度。
默认旋转中心点是Canvas的左上角(0, 0)坐标点,如果希望改变旋转中心点,例如以Canvas画布的中心旋转,需要先使用translate()位移旋转中心点。

角度转弧度计算公式是:radian = degree * Math.PI / 180。例如,旋转45°,旋转弧度就是45 * Math.PI / 180

rotate(angle);
// angle : Canvas画布坐标系旋转的角度,单位是弧度。注意,此旋转和CSS3的旋转变换不一样,旋转的是坐标系,而非元素。因此,实际开发的时候,旋转完毕,需要将坐标系再还原。

画布和图片同步旋转 demo :

var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')

var width = canvas2.width;
var height = canvas2.height;
// 加载图片素材
var img = new Image();
img.onload = function () {
    // 先位移坐标到中心
    context.translate(width / 2, height / 2);
    // 旋转90度
    context.rotate(90 * Math.PI / 180);
    // 此时按照旋转后的尺寸
    // 把定位中心移动到左上角
    context.translate(-1 * height / 2, -1 * width / 2);
    // 绘制图片
    context.drawImage(this, 0, 0, height, width);
    // 坐标系还原到初始
    context.setTransform(1, 0, 0, 1, 0, 0);
};
img.src = './1.jpg';

缩放

根据 x 水平方向和 y 垂直方向,为canvas 单位添加缩放变换的方法。

scale()用来缩放Canvas画布的坐标系,只是影响坐标系,之后的绘制会受此方法影响,但之前已经绘制好的效果不会有任何变化。
默认缩放中心点是Canvas的左上角(0, 0)坐标点,如果希望改变缩放中心点,需要先使用translate()方法进行位移。

ctx.scale(x, y)
// x : Canvas坐标系水平缩放的比例。支持小数,如果值是-1,表示水平翻转。
// y : Canvas坐标系垂直缩放的比例。支持小数,如果值是-1,表示垂直翻转。

位移

将 canvas 按原始 x点的水平方向、原始的 y点垂直方向进行平移变换

ctx.translate(x, y);

矩阵

transform() 方法可以对当前坐标系进行进一步变换,以实现缩放,旋转,拉伸或者位移效果。
此方法和setTransform()方法的区别在于,后者一旦执行会完全重置已有的变换,transform()方法则是累加。

  • transform(a, b, c, d, e, f) 将当前的变形矩阵乘上一个基于自身参数的矩阵
  • setTransform(a, b, c, d, e, f) 将当前的变形矩阵重置为单位矩阵。
  • resetTransform() 重置当前变形为单位矩阵,它和调用以下语句是一样的:ctx.setTransform(1, 0, 0, 1, 0, 0);
context.transform(a, b, c, d, e, f);
/*
a:水平缩放(默认值1,单位倍数)
b:水平倾斜(默认值0,单位弧度)
c:垂直倾斜(默认值0,单位弧度)
d:垂直缩放(默认值1,单位倍数)
e:水平位移(默认值0,单位像素)
f:垂直位移(默认值0,单位像素)
*/

下面是一个例子。

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// step 1
ctx.transform(2, 0, 0, 1, 50, 50);
ctx.fillRect(0, 0, 100, 100);
// step 2
ctx.setTransform(1, 0, 0, 1, 0, 100);
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 100, 100);

上面代码中:step1将原始图形是 100 x 100 的矩形,结果缩放成 200 x 100 的矩形,并且左上角从(0, 0)移动到(50, 50)。step2 将重置当前矩阵,无缩放、无旋转,将画布中心点移至(0, 100)

注意:多个transform()方法具有叠加效果。

图像处理

绘制图片

Canvas API 允许将图像文件写入画布,做法是读取图片后,使用drawImage()方法将这张图片放上画布。

CanvasRenderingContext2D.drawImage()有三种使用格式。

ctx.drawImage(image, dx, dy);
ctx.drawImage(image, dx, dy, dWidth, dHeight);
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

各个参数的含义如下。

  • image:图像元素
  • sx:图像内部的横坐标,用于映射到画布的放置点上。
  • sy:图像内部的纵坐标,用于映射到画布的放置点上。
  • sWidth:图像在画布上的宽度,会产生缩放效果。如果未指定,则图像不会缩放,按照实际大小占据画布的宽度。
  • sHeight:图像在画布上的高度,会产生缩放效果。如果未指定,则图像不会缩放,按照实际大小占据画布的高度。
  • dx:画布内部的横坐标,用于放置图像的左上角
  • dy:画布内部的纵坐标,用于放置图像的右上角
  • dWidth:图像在画布内部的宽度,会产生缩放效果。
  • dHeight:图像在画布内部的高度,会产生缩放效果。

切片 Slicing

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

const img = new Image()
img.crossOrigin = 'anonymous'   // 解决图片跨域问题
img.onload = function() {
  // 拉伸图片同时保持图片比例
  ctx.drawImage(img, 0, 42, 500, 250, 0, 0, 300, 150)
}
img.src = 'https://www.canvasapi.cn/assets/images/examples/500/1.jpg' 	// 图片实际宽高 500333

如何让一张尺寸为500*300图片填满尺寸为300*150Canvas画布,同时保持图片的原始比例呢?这个就需要用到sx,sy,sWidth和sHeight这几个参数。

上面的示例关键如何理解 0, 42, 500, 250 这4个值是怎么计算来的。我们最终图片要显示在300*150大小的Canvas画布中,比例是2:1,因此,我们最终设置的用来绘制的图片尺寸比例也是2:1。原始图片宽度是500,要保持2:1,则高度我们就设置为250;而原始高度是333,我们希望显示图片中心区域,因此起始垂直坐标计算下,(333 - 250) / 2,四舍五入就是42,因此,就有了对原始图片的剪裁坐标值和尺寸值0, 42, 500, 250

像素读写

  • CanvasRenderingContext2D.getImageData():将画布读取成一个 ImageData 对象
  • CanvasRenderingContext2D.putImageData():将 ImageData 对象写入画布
  • CanvasRenderingContext2D.createImageData():生成 ImageData 对象

getImageData()

CanvasRenderingContext2D.getImageData()方法用来读取<canvas>的内容,返回一个 ImageData 对象,包含了每个像素的信息。

context.getImageData(sx, sy, sWidth, sHeight)

getImageData()方法接受四个参数。sxsy是读取区域的左上角坐标,sWidthsHeight是读取区域的宽度和高度。如果想要读取整个<canvas>区域,可以写成下面这样。

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

getImageData()方法返回的是一个ImageData对象。该对象有三个属性。

  • ImageData.data:一个一维数组。该数组的值,依次是每个像素的红、绿、蓝、alpha 通道值(每个值的范围是 0~255),因此该数组的长度等于图像的像素宽度 x 图像的像素高度 x 4。这个数组不仅可读,而且可写,因此通过操作这个数组,就可以达到操作图像的目的。
  • ImageData.width:浮点数,表示 ImageData 的像素宽度。
  • ImageData.height:浮点数,表示 ImageData 的像素高度。

putImageData()

CanvasRenderingContext2D.putImageData()方法将ImageData对象的像素绘制在<canvas>画布上。该方法有两种使用格式。

ctx.putImageData(imagedata, dx, dy)
ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)

该方法有如下参数。

  • imagedata:包含像素信息的 ImageData 对象。
  • dx:<canvas>元素内部的横坐标,用于放置 ImageData 图像的左上角。
  • dy:<canvas>元素内部的纵坐标,用于放置 ImageData 图像的左上角。
  • dirtyX:ImageData 图像内部的横坐标,用于作为放置到<canvas>的矩形区域的左上角的横坐标,默认为0。
  • dirtyY:ImageData 图像内部的纵坐标,用于作为放置到<canvas>的矩形区域的左上角的纵坐标,默认为0。
  • dirtyWidth:放置到<canvas>的矩形区域的宽度,默认为 ImageData 图像的宽度。
  • dirtyHeight:放置到<canvas>的矩形区域的高度,默认为 ImageData 图像的高度。

createImageData()

CanvasRenderingContext2D.createImageData()方法用于生成一个空的ImageData对象,所有像素都是透明的黑色(即每个值都是0)。该方法有两种使用格式。

ctx.createImageData(width, height)
ctx.createImageData(imagedata)

createImageData()方法的参数如下。

  • width:ImageData 对象的宽度,单位为像素。
  • height:ImageData 对象的高度,单位为像素。
  • imagedata:一个现有的 ImageData 对象,返回值将是这个对象的拷贝。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imageData = ctx.createImageData(100, 100);

上面代码中,imageData是一个 100 x 100 的像素区域,其中每个像素都是透明的黑色。

4. 动画

canvas画布可能最大的限制就是图像一旦绘制出来,它就是一直保持那样了。如果需要移动它,我们不得不对所有东西(包括之前的)进行重绘。重绘是相当费时的,而且性能很依赖于电脑的速度。

动画的基本步骤:

可以通过以下的步骤来画出一帧:

  1. 清空 canvas
    除非接下来要画的内容会完全充满 canvas (例如背景图),否则你需要清空所有。最简单的做法就是用 clearRect 方法。
  2. 保存 canvas 状态
    如果你要改变一些会改变 canvas 状态的设置(样式,变形之类的),又要在每画一帧之时都是原始状态的话,你需要先保存一下。
  3. 绘制动画图形(animated shapes)
    这一步才是重绘动画帧。
  4. 恢复 canvas 状态
    如果已经保存了 canvas 的状态,可以先恢复它,然后重绘下一帧。

5. canvas元素方法

Canvas.getContext()

``HTMLCanvasElement.getContext()` 返回canvas 的上下文,如果上下文没有定义则返回 null

// 语法
canvas.getContext(contextType);
canvas.getContext(contextType, contextAttributes);

参数说明

  • contextType : String

    • 2d : 创建并返回一个CanvasRenderingContext2D对象,主要用来进行2d绘制,也就是二维绘制,平面绘制。

    • webglexperimental-webgl : 此参数可以返回一个WebGLRenderingContext(WebGL渲染上下文)对象,WebGL(全写Web Graphics Library)是一种3D绘图协议,可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型,无需安装任何其他插件。此参数对应的WebGL版本1(OpenGL ES 2.0)。

    • webgl2 : 此参数可以返回一个WebGL2RenderingContext对象,可以用来绘制三维3D效果。此参数对应的WebGL版本2(OpenGL ES 3.0)。不过目前这个还处于试验阶段,我们实际Kaufman都是使用'webgl'这个参数。

    • bitmaprenderer : 创建一个ImageBitmapRenderingContext(位图渲染上下文),可以借助给定的ImageBitmap替换Canavs的内容。

  • contextAttributes :(可选)Object
    contextAttributes为一个纯对象参数

Canvas.toDataURL()

<canvas>元素的toDataURL()方法,可以将 Canvas 数据转为 Data URI 格式的图像。

canvas.toDataURL(type, quality)

toDataURL()方法接受两个参数。

  • type:字符串,表示图像的格式。默认为image/png,另一个可用的值是image/jpeg,Chrome 浏览器还可以使用image/webp
  • quality:浮点数,0到1之间,表示 JPEG 和 WebP 图像的质量系数,默认值为0.92。

该方法的返回值是一个 Data URI 格式的字符串。

function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL('image/png');
  return image;
}

上面的代码将<canvas>元素,转化成PNG Data URI。

var fullQuality = canvas.toDataURL('image/jpeg', 0.9);
var mediumQuality = canvas.toDataURL('image/jpeg', 0.6);
var lowQuality = canvas.toDataURL('image/jpeg', 0.3);

上面代码将<canvas>元素转成高画质、中画质、低画质三种 JPEG 图像。

Canvas.toBlob()

HTMLCanvasElement.toBlob()方法用于将<canvas>图像转成一个 Blob 对象,默认类型是image/png。它的使用格式如下。

// 格式
canvas.toBlob(callback, mimeType, quality)

// 示例
canvas.toBlob(function (blob) {...}, 'image/jpeg', 0.95)

toBlob()方法可以接受三个参数。

  • callback:回调函数。它接受生成的 Blob 对象作为参数。
  • mimeType:字符串,图像的 MIMEType 类型,默认是image/png
  • quality:浮点数,0到1之间,表示图像的质量,只对image/jpegimage/webp类型的图像有效。

注意,该方法没有返回值。

下面的例子将<canvas>图像复制成<img>图像。

var canvas = document.getElementById('myCanvas');
function blobToImg(blob) {
  var newImg = document.createElement('img');
  var url = URL.createObjectURL(blob);
  newImg.onload = functio () {
    // 使用完毕,释放 URL 对象
    URL.revokeObjectURL(url);
  };
  newImg.src = url;
  document.body.appendChild(newImg);
}
canvas.toBlob(blobToImg);

@Marinerer
Copy link
Owner Author

HTML Canvas 参考手册

来源1:https://www.w3school.com.cn/tags/html_ref_canvas.asp
来源2:https://www.w3cschool.cn/htmltags/ref-canvas.html

HTML <canvas> 标签用于通过脚本(通常是 JavaScript)动态绘制图形。

描述

HTML5 <获得用于在画布上绘图的对象获得用于在画布上绘图的对象> 标签用于绘制图像(通过脚本,通常是 JavaScript)。

不过,<canvas> 元素本身并没有绘制能力(它仅仅是图形的容器) - 您必须使用脚本来完成实际的绘图任务。

getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。

本手册提供完整的 getContext("2d") 对象的属性和方法,可用于在画布上绘制文本、线条、矩形、圆形等等。

颜色、样式和阴影

属性 描述
fillStyle 设置或返回用于填充绘画的颜色、渐变或模式。
strokeStyle 设置或返回用于笔触的颜色、渐变或模式。
shadowColor 设置或返回用于阴影的颜色。
shadowBlur 设置或返回用于阴影的模糊级别。
shadowOffsetX 设置或返回阴影与形状的水平距离。
shadowOffsetY 设置或返回阴影与形状的垂直距离。
方法 描述
createLinearGradient() 创建线性渐变(用在画布内容上)。
createPattern() 在指定的方向上重复指定的元素。
createRadialGradient() 创建放射状/环形的渐变(用在画布内容上)。
addColorStop() 规定渐变对象中的颜色和停止位置。

线条样式

属性 描述
lineCap 设置或返回线条的结束端点样式。
lineJoin 设置或返回两条线相交时,所创建的拐角类型。
lineWidth 设置或返回当前的线条宽度。
miterLimit 设置或返回最大斜接长度。

矩形

方法 描述
rect() 创建矩形。
fillRect() 绘制"被填充"的矩形。
strokeRect() 绘制矩形(无填充)。
clearRect() 在给定的矩形内清除指定的像素。

路径

方法 描述
fill() 填充当前绘图(路径)。
stroke() 绘制已定义的路径。
beginPath() 起始一条路径,或重置当前路径。
moveTo() 把路径移动到画布中的指定点,不创建线条。
closePath() 创建从当前点回到起始点的路径。
lineTo() 添加一个新点,然后在画布中创建从该点到最后指定点的线条。
clip() 从原始画布剪切任意形状和尺寸的区域。
quadraticCurveTo() 创建二次贝塞尔曲线。
bezierCurveTo() 创建三次贝塞尔曲线。
arc() 创建弧/曲线(用于创建圆形或部分圆)。
arcTo() 创建两切线之间的弧/曲线。
isPointInPath() 如果指定的点位于当前路径中,则返回 true,否则返回 false。

转换

方法 描述
scale() 缩放当前绘图至更大或更小。
rotate() 旋转当前绘图。
translate() 重新映射画布上的 (0,0) 位置。
transform() 替换绘图的当前转换矩阵。
setTransform() 将当前转换重置为单位矩阵。然后运行 transform()。

文本

属性 描述
font 设置或返回文本内容的当前字体属性。
textAlign 设置或返回文本内容的当前对齐方式。
textBaseline 设置或返回在绘制文本时使用的当前文本基线。
方法 描述
fillText() 在画布上绘制"被填充的"文本。
strokeText() 在画布上绘制文本(无填充)。
measureText() 返回包含指定文本宽度的对象。

图像绘制

方法 描述
drawImage() 向画布上绘制图像、画布或视频。

像素操作

属性 描述
width 返回 ImageData 对象的宽度。
height 返回 ImageData 对象的高度。
data 返回一个对象,其包含指定的 ImageData 对象的图像数据。
方法 描述
createImageData() 创建新的、空白的 ImageData 对象。
getImageData() 返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据。
putImageData() 把图像数据(从指定的 ImageData 对象)放回画布上。

合成

属性 描述
globalAlpha 设置或返回绘图的当前 alpha 或透明值。
globalCompositeOperation 设置或返回新图像如何绘制到已有的图像上。

其他

方法 描述
save() 保存当前环境的状态。
restore() 返回之前保存过的路径状态和属性。
createEvent() 创建新的 Event 对象
getContext() 获得用于在画布上绘图的对象
toDataURL() 导出在 canvas 元素上绘制的图像

@Marinerer Marinerer changed the title Canvas文档教程 Canvas文档 Oct 13, 2022
@Marinerer
Copy link
Owner Author

Marinerer commented Oct 13, 2022

awesome-canvas

精心收录Canvas相关的资源并整理分类,部分同类资源库也收录SVG/WebGL相关的资源。

简体中文 | English

目录

教程

书籍

仓库

图形绘制

3D库

VR/AR

物理引擎

游戏引擎

  • Hilo [在线演示] - 阿里巴巴集团开发的跨平台HTML5游戏开发解决方案
  • melonJS [在线演示] - 一个全新的轻量级javascript游戏引擎
  • Babylon.js [在线演示] - 功能强大、美观、简单、开源、封装友好的游戏渲染引擎
  • Phaser [在线演示] - 有趣、免费、快速、支持Canvas和WebGL的2D游戏框架,用于为桌面和移动端浏览器H5游戏制作
    • phaser-examples - 包含数百个Phaser HTML5 游戏框架的源代码示例
    • games - 一个基于Phaser的小游戏集合
    • phaser3-examples - phaser3例子
    • phaser-ce - Phaser CE 是一个有趣、免费且快速的2D游戏框架,用于为桌面和移动端Web制作HTML5游戏,支持 Canvas和WebGL渲染
    • phaser3-project-template - Phaser3项目模板
  • taro [在线演示] - 轻量级3D游戏引擎。
  • turbulenz_engine [在线演示] - 模块化的3D和2D游戏框架,用于为浏览器、桌面端和移动端设备制作 HTML5 驱动的游戏。

流程图

甘特图

组织图

图编辑

电子表格

图表库

  • D3 [在线演示] - D3(或D3.js)是一个用于web标准可视化数据的JS库

  • echarts [在线演示] - 一个强大的交互式图表和数据可视化库

  • Chart.js [在线演示] - 给开发和设计人员的简单而灵活的js图表

  • AntV - 蚂蚁集团全新一代数据可视化解决方案

    • G2 [在线演示] - 一套面向常规统计图表,以数据驱动的高交互可视化图形语法。
    • G6 [在线演示] - ♾ G6 是一个简单、易用、完备的图可视化引擎
    • G [在线演示] - G 作为 AntV 底层的渲染引擎,致力于为上层产品提供一致、高性能的 2D / 3D 图形渲染能力,适配 Web 端全部底层渲染 API(Canvas2D / SVG / WebGL / WebGPU)。
    • X6 [在线演示] - 🚀 X6 是 AntV 旗下的图编辑引擎。
    • S2 [在线演示] - 数据驱动的多维分析表格。
    • L7 [在线演示] - 🌎 蚂蚁金服 AntV 数据可视化团队推出的基于 WebGL 的开源大规模地理空间数据可视分析开发框架。
    • F2 [在线演示] - 一个专注于移动,开箱即用的可视化解决方案,完美支持 H5 环境同时兼容多种环境(node, 小程序,weex)
    • F6 [在线示例] - F6是一款可以快速、流畅运行于移动设备中的图可视化引擎
    • F2Native [在线演示] - F2Native 是一个专注于客户端,开箱即用、高性能的可视化解决方案,完备的图形语法理论,满足你的各种需求,专业的移动设计指引为你带来最佳的移动端图表体验。
    • G2Plot [在线演示] - 基于图形语法(the Grammar of Graphics)的图表库。
    • Graphin [在线示例] - 基于G6封装的React组件库,专注在关系可视分析领域,简单高效,开箱即用
    • XFlow [在线示例] - 基于X6图编辑引擎、面向React技术栈用户的专业图编辑应用级解决方案
    • L7Plot [在线示例] - 简单易用、图表丰富、支持定制的地理空间数据可视化地理图表库。
    • Ant Design Charts [在线示例] - 简单好用的 React 图表库。
    • AVA [在线示例] - AVA 是为了更简便的可视分析而生的技术框架。 VA 代表可视分析(Visual Analytics),而第一个 A 具有多重涵义:其目标是成为一个自动化(Automated)、智能驱动(AI driven)、支持增强分析(Augmented)的可视分析解决方案。
    • Viser [在线示例] - 基于G2的适合数据可视化工程师的工具包。支持React、Vue和AngularJS。
  • highcharts [在线演示] - 基于SVG的JavaScript图表库,支持旧浏览器

  • wx-charts [在线演示] - 微信小程序图表charts组件

  • wordcloud2.js [在线演示] - 2D Canvas/Html词云

  • chartist-js [在线演示] - 简单的响应式图表

  • charts [在线演示] - 零依赖的、简单的、响应快的、现代SVG图表

  • flot [在线演示] - 基于Jquery为工程和科学应用程序派生的JS绘图库

  • apexcharts.js [在线演示] - 基于SVG的交互式JavaScript图表

  • plotly.js [在线演示] - Ploty和Dash的JavaScript版本的开源图表库

  • easy-pie-chart - 一个轻量级插件,为单个值绘制简单带动画的饼图

  • react-vis [在线演示] - React的数据可视化组件

  • vega [在线演示] - 可视化语法,使用Vega,您可以用JSON格式描述数据可视化,并使用HTML5 Canvas或SVG生成交互式视图

  • heatmap.js - 基于HTML5 Canvas的Js热力图

  • zeu [在线演示] - 用于构建实时电视仪表板、监控UI和物联网Web界面的JS库

  • HQChart - HQChart - H5, 微信小程序 沪深/港股/数字货币/期货/美股 K线图(kline),走势图,缩放,拖拽,十字光标,画图工具,截图,筹码图

  • canvas-gauges [在线演示] - 使用纯 JavaScript 和 HTML5 画布的高度可配置仪表盘。没有依赖性。由于代码库最少,因此适用于物联网设备

海报截图

数据处理

  • html2pdf.js - 纯JS的客户端HTML生成PDF
  • rasterizeHTML.js - 将HTML渲染到浏览器的Canvas中
  • JavaScript-Canvas-to-Blob - 一个将Canvas元素转换为Blob对象的函数
  • jsgif - 将HTML5 Canvas保存到GIF和动画。一个AS3GIF Gifplayer到JS的港口
  • whammy - 基于Canvas来Hack的实时JS webm编码器
  • js-imagediff - 带有Jasmine匹配器的Canvas图像差异比对程序,用于测试Canvas

图像处理

画板

签名

波纹动画

粒子动画

路径动画

二维码

验证码

运行时

其他

插件资源网站

效果/案例

文章

@Marinerer
Copy link
Owner Author

Marinerer commented Mar 26, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant