Canvas基础知识1

基础内容

  • <canvas> 标签只有两个属性—— widthheight(可选),默认值(width:300px,height:150px); 它们表示画布的实际宽度和高度,绘制的图形都在这上面。而style中的width和height则是canvas在浏览器中被渲染的宽度和高度。两者比例不一样会出现扭曲。
  • <canvas>标签的替换内容,不支持<canvas>的浏览器会忽略容器并在其中渲染后备内容。
    <canvas id="stockGraph" width="150" height="150">
      current stock price: $3.15 +0.15
    </canvas>
    
    <canvas id="clock" width="150" height="150">
      <img src="images/clock.png" width="150" height="150" alt=""/>
    </canvas>
    
  • </canvas> 标签不可省, 否则文档其余部分会被认为是替代内容,将不会显示出来。
  • <canvas> 元素创造了一个固定大小的画布,它公开了一个或多个渲染上下文,其可以用来绘制和处理要展示的内容。可以通过getContext()方法(只有一个参数:上下文的格式)来获得渲染上下文和它的绘画功能。
    var canvas = document.getElementById('tutorial');
    var ctx = canvas.getContext('2d');
    
  • 检测支持性
    var canvas = document.getElementById('tutorial');
    if (canvas.getContext){
          
          
      var ctx = canvas.getContext('2d');
      // drawing code here
    } else {
          
          
      // canvas-unsupported code here
    }
    

绘制图形

<canvas>只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)

canvas提供了三种方法绘制矩形:

  1. fillRect(x, y, width, height) 绘制一个填充的矩形
  2. strokeRect(x, y, width, height) 绘制一个矩形的边框
  3. clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明

绘制路径

基本步骤:

  1. 创建路径起始点
  2. 使用画图命令去画出路径
  3. 把路径封闭
  4. 可通过描边或填充路径区域来渲染图形

所用到的函数:

  1. beginPath()
    • 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径
    • 本质上,路径是由很多子路径构成,这些子路径都是在一个列表中,所有的子路径(线、弧形、等等)构成图形。而每次这个方法调用之后,列表清空重置,然后我们就可以重新绘制新的图形。
    • 注意:当前路径为空,即调用beginPath()之后,或者canvas刚建的时候,第一条路径构造命令通常被视为是moveTo(),出于这个原因,你几乎总是要在设置路径之后专门指定你的起始位置。
  2. closePath()
    • 闭合路径之后,图形绘制命令又重新指向到上下文中。
    • 该方法不是必须的。
    • 调用fill()函数时,没有闭合的形状都会自动闭合。调用stroke()不会自动闭合。
  3. stroke
    通过线条来绘制图形轮廓
  4. fill()
    通过填充路径的内容区域生成实心的图形

代码示例:

function draw() {
    
    
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    
    
    var ctx = canvas.getContext('2d');

    ctx.beginPath();
    ctx.moveTo(75, 50);
    ctx.lineTo(100, 75);
    ctx.lineTo(100, 25);
    ctx.fill();
  }
}

在这里插入图片描述

移动笔触

  • moveTo(x, y)
    将笔触移动到指定的坐标x以及y上
    可以使用moveTo()来绘制一些不连续的路径。

代码示例:

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.stroke();

在这里插入图片描述

绘制线

lineTo(x, y)
绘制一条从当前位置到指定(x, y)位置的直线

绘制圆弧

  • arc(x, y, radius, startAngle, endAngle, anticlockwise)
    • 画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。
    • 注意:arc()函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:
      弧度=(Math.PI/180)*角度
  • arcTo(x1, y1, x2, y2, radius)
    • 根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点
    • x1, y1 第一个控制点的坐标;x2, y2 第二个控制点的坐标, radius圆弧的半径

绘制二次贝塞尔曲线及三次贝塞尔曲线

  • quadraticCurveTo(cp1x, cp1y, x, y)
    绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
    绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。
// 二次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(75, 25);
ctx.quadraticCurveTo(25, 25, 25, 62.5);
ctx.quadraticCurveTo(25, 100, 50, 100);
ctx.quadraticCurveTo(50, 120, 30, 125);
ctx.quadraticCurveTo(60, 120, 65, 100);
ctx.quadraticCurveTo(125, 100, 125, 62.5);
ctx.quadraticCurveTo(125, 25, 75, 25);
ctx.stroke();

在这里插入图片描述

//三次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(75, 40);
ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
ctx.fill();

在这里插入图片描述

绘制矩形

除了直接在画布上绘制矩形的三个额外方法:

  1. fillRect(x, y, width, height) 绘制一个填充的矩形
  2. strokeRect(x, y, width, height) 绘制一个矩形的边框
  3. clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明

还有rect()方法,将一个矩形路径增加到当前的路径上
rect(x, y, width, height)
绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。

当该方法执行的时候,moveTo()方法自动设置坐标参数(0,0)。也就是说,当前笔触自动重置回默认坐标。

Path2D对象

Path2D() (实验中的功能,浏览器兼容性迷)

  • Path2D() 构造函数返回一个新的 Path2D 对象的实例,可以选择另一条路径作为参数(创建一个拷贝),或者选择 SVG path 数据构成的字符串。
    new Path2D();     // 空的Path对象
    new Path2D(path); // 克隆Path对象
    new Path2D(d);    // 从SVG建立Path对象
    
  • Path2D API 添加了 addPath作为将path结合起来的方法。当你想要从几个元素中来创建对象时,这将会很实用。比如:
    Path2D.addPath(path [, transform])​
    添加了一条路径到当前路径(可能添加了一个变换矩阵)
    MDN Path2D()

图形上色

默认情况下,为黑色

  • fillStyle 设置图形的填充颜色
  • strokeStyle 设置图形的轮廓颜色

设置透明度
globalAlpha = transparencyValue

  • 这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
  • 该属性在绘制大量拥有相同透明度的图形时候相当高效。

其实可以直接通过rgba()的形式,设置透明度

设置线的样式

  • lineWidth = value 设置线条宽度

  • lineCap = type 设置线条末端样式: butt round square
    在这里插入图片描述

  • lineJoin = type 设置线条与线条间接合处的样式: round bevel miter(默认)
    在这里插入图片描述

  • miterLimit = value 限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。

  • getLineDash()返回一个包含当前虚线样式,长度为非负偶数的数组。

  • setLineDash(segments)设置当前虚线样式。接受一个数组,来指定线段与间隙的交替

  • lineDashOffset = value 设置虚线样式的起始偏移量。

渐变

  • createLinearGradient(x1, y1, x2, y2)
    (x1, y1) 渐变的起点 (x2, y2) 渐变的终点
  • createRadialGradient(x1, y1, r1, x2, y2, r2)
    var lineargradient = ctx.createLinearGradient(0,0,150,150);
    var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);
    

可以使用addColorStop方法给它上色
gradient.addColorStop(position, color)
position 是一个0.0 到1.0之间的数值,表示渐变中颜色所在的相对位置。

图案样式

createPattern(image, type)
image 可以是一个Image对象的引用,或者另一个canvas对象。
type: 必须是下面的字符串值之一: repeat repeat-x repeat-y no-repeat
注意: 用 canvas 对象作为 Image 参数在 Firefox 1.5 (Gecko 1.8) 中是无效的。

var img = new Image();
img.src = 'someimage.png';
var ptrn = ctx.createPattern(img,'repeat');

注意: 与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。

阴影

  • shadowOffsetX = float shadowOffsetY = float
    用来设定阴影在x和y轴的延伸距离。负值向上向左延伸,正值向下向右延伸。默认为0
  • shadowBlur = float
    用于设定阴影的模糊程度,默认0
  • shadowColor = color
    设定阴影的颜色效果,默认全透明的黑色

Canvas填充规则

当我们用到 fill(或者clipisPointinPath )你可以选择一个填充规则,该填充规则根据某处在路径的外面或者里面来决定该处是否被填充,这对于自己与自己路径相交或者路径被嵌套的时候是有用的。

值:

  • “nonzero”: non-zero winding rule, 默认值.
  • “evenodd”: even-odd winding rule.

绘制文本

  • fillText(text, x, y [, maxWidth])
    在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的
  • strokeText(text, x, y [, maxWidth])
    在指定的(x, y) 位置绘制文本边框,绘制的最大宽度是可选的

设置文本样式:

  • font = value 默认字体10px sans-serif
  • textAlign = value 文本对齐选项, 可选值包括: start end left right center 默认值为start
  • textBaseline = value 基线对齐选项,可选值包括: top hanging middle alphabetic ideographic bottom 默认值为alphabetic
  • direction = value 文本方向 可选值: ltr rtl inherit 默认值为:inherit

预测量文本宽度:

  • measureText()
    将返回一个TextMetrics对象的宽度,所在像素,这些体现文本特性的属性

使用图像

基本步骤:
  1. 获得图片源(HTMLImageElement对象/canvas元素的引用/图片URL)
  2. 使用drawImage() 函数将图片绘制到画布上
图片源:
  1. HTMLImageElement :由Image()函数构造出来的,或者任何的<img>元素
  2. HTMLVideoElement<video>元素作为图片源,可以从当前视频中抓取当前帧作为一个图像
  3. HTMLCanvasElement<canvas>元素作为图片源
  4. ImageBitmap:一个高性能的位图,可以低延迟的绘制,它可以从上述的所有源以及其它几种源中生成

这些源统一由CanvasImageSource类型来引用
MDN 使用图像 Using images

缩放Scaling

drawImage(image, x, y, width, height)
这个方法多了2个参数:width 和 height,这两个参数用来控制 当向canvas画入时应该缩放的大小

切片Slicing

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。其它8个参数最好是参照右边的图解,前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。

过渡缩放图像可能会导致图像模糊或像素化,可以使用绘图环境的imageSmoothingEnabled属性来控制是否在缩放图像时使用平滑算法。默认值为true,即启用平滑缩放。

变形

变形是一种更强大的方法,可以将原点移动到另一点、对网格进行旋转和缩放。

状态的保存和恢复

  • save() 保存画布(canvas)的所有状态
  • restore()
    saverestore方法是用来保存和恢复canvas状态的,都没有参数。
    canvas的状态就是当前画面应用的所有样式和变形的一个快照。
    你可以调用任意多次save方法,每一次调用restore方法,上一个保存的状态就从栈中弹出,所有设定都恢复。

移动

translate(x, y)
translate 方法接受两个参数。x 是左右偏移量,y 是上下偏移量,如右图所示。

旋转

rotate(angle)
这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate 方法。

缩放

scale(x, y)
缩放画布的水平和垂直的单位。

变形

transform(a, b, c, d, e, f)
这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵
如果任意一个参数是Infinity,变形矩阵也必须被标记为无限大,否则会抛出异常
参数如下:

  • a(m11) 水平方向的缩放
  • b(m12) 竖直方向的倾斜偏移
  • c(m21) 水平方向的倾斜偏移
  • d(m22) 竖直方向的缩放
  • e(dx) 水平方向的移动
  • f(dy) 竖直方向的移动

setTransform(a, b, c, d, e, f)
这个方法会将当前的变形矩阵重置为单位矩阵,然后用相同的参数调用 transform 方法。如果任意一个参数是无限大,那么变形矩阵也必须被标记为无限大,否则会抛出异常。从根本上来说,该方法是取消了当前变形,然后设置为指定的变形,一步完成。

resetTransform()
重置当前变形为单位矩阵,它和调用以下语句是一样的:ctx.setTransform(1, 0, 0, 1, 0, 0);

组合Compositing

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

裁切路径

裁切路径和普通的 canvas 图形差不多,不同的是它的作用是遮罩,用来隐藏不需要的部分。如右图所示。红边五角星就是裁切路径,所有在路径以外的部分都不会在 canvas 上绘制出来。

clip()
将当前正在构建的路径转换为当前的裁剪路径。

动画

动画的基本步骤

  1. 清空canvas: clearRect()
  2. 保存canvas状态: 改变一些会改变canvas状态的设置,又要在每画一帧之时都是原始状态的话,需要保存一下
  3. 绘制动画图形: 重绘动画帧
  4. 恢复canvas状态

操控动画

  • setInterval(function, delay)
    设定好间隔时间后,function会定期执行
  • setTimeout(function, delay)
    在设定好的时间之后执行函数
  • requestAnimationnFrame(callback)
    告诉浏览器你希望执行一个动画,并在重绘之前,请求浏览器执行一个特定的函数来更新动画

注意: 采用 window.requestAnimationFrame()实现动画效果。这个方法提供了更加平缓并更加有效率的方式来执行动画,当系统准备好了重绘条件的时候,才调用绘制动画帧。一般每秒钟回调函数执行60次,也有可能会被降低。

像素操作

ImageData对象

ImageData对象中存储着canvas对象真实的像素数据,它包含以下几个只读属性:

  • width 图片宽度,单位是像素
  • height 图片高度,单位是像素
  • data
    Uint8ClampedArray 类型的一维数组,包含着RGBA格式的整型数据,范围在0至255之间(包括255)
    包含高度 x 宽度 x 4 bytes数据,索引值从0到(高度 x 宽度 x 4)- 1

创建一个ImageData 对象

  • createImageData()
    创建了一个新的具体特定尺寸的ImageData对象。所有像素被预设为透明黑。

    var myImageData = ctx.createImageData(width, height);
    

    创建一个被anotherImageData对象指定的相同像素的ImageData对象。这个新的对象像素全部被预设为透明黑。这个并非复制了图片数据。

    var myImageData = ctx.createImageData(anotherImageData);
    

得到场景像素数据

  • getImageData() 方法
var myImageData = ctx.getImageData(left, top, width, height);

注意: 任何在画布以外的元素都会被返回成一个透明黑的ImageData对像。

在场景中写入像素数据

  • putImageData: 对场景进行像素数据的写入
    ctx.putImageData(myImageData, dx, dy);
    

dx 和 dy 参数表示你希望在场景内左上角绘制的像素数据所得到的设备坐标

通过修改像素数据的数值,可以对图形进行灰度处理和反相颜色处理

缩放和反锯齿
imageSmoothingEnabled 反锯齿, 默认是启用的。

保存图片
HTMLCanvasElement 提供一个toDataURL()方法。 它返回一个包含被类型参数规定的的图像表现格式的数据链接。返回的图片分辨率是96dpi.

  • canvas.toDataURL('image/png') 默认设定。创建一个PNG图片
  • canvas.toDataURL('image/jpeg', quality) 创建一个JPG图片。你可以有选择地提供从0到1的品质质量,1表示最好品质,0基本不被解析,但有比较小的文件大小。
  • 你可以将数据链接用于任何<image> 元素,或者将它放在一个有download属性的超链接里用于保存到本地。
  • canvas.toBlob(callback, type, encoderOptions)
  • 这个创建了一个在画布中的代表图片的Blob对象

猜你喜欢

转载自blog.csdn.net/weixin_40693643/article/details/110374252