美文网首页
2022-08-28 canvas 学习笔记

2022-08-28 canvas 学习笔记

作者: FConfidence | 来源:发表于2022-08-28 03:27 被阅读0次

    Canvas

    基本用法

    1. 绘制矩形的三种方式

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

      • beginPath() 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。 (函数准备绘制一个新的形状路径开始)
      • moveTo(x, y) 要在设置路径(beginPath)之后专门指定你的起始位置。
      • closePath() 闭合路径之后图形绘制命令又重新指向到上下文中。
      • stroke() 通过线条来绘制图形轮廓。
      • fill() 通过填充路径的内容区域生成实心的图形。
    3. moveTo 移动笔触

      • 将笔触移动到指定的坐标 x 以及 y 上。
    4. 绘制直线: lineTo(x, y) 绘制一条从当前位置指定 (x,y) 位置的直线。

    5. 绘制圆弧:

      • arc(x, y, radius, startAngle, endAngle, anticlockwise): 画一个以(x,y)为圆心的以 radius 为半径的圆弧(圆),从 startAngle 开始到 endAngle 结束,按照 anticlockwise 给定的方向(默认为顺时针)来生成。
      • arcTo(x1, y1, x2, y2, radius): 根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。
      • 弧度=(Math.PI/180)*角度。
      // 弧度方向 (顺时针的计算)
                  2 * PI
      3/2 * PI                  0
                  PI
      
    6. 二次/三次贝塞尔曲线

      • quadraticCurveTo(cp1x, cp1y, x, y)
      • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
    7. 直接在画布上绘制矩形的三个额外方法

      • rect(x, y, width, height) 当该方法执行的时候,moveTo() 方法自动设置坐标参数(0,0)。也就是说,当前笔触自动重置回默认坐标。
    8. Path2D 对象: 用来缓存或记录绘画命令

      • Path2D.addPath(path [, transform])

        new Path2D(); // 空的 Path 对象
        new Path2D(path); // 克隆 Path 对象
        new Path2D(d); // 从 SVG 建立 Path 对象
        
        const rectangle = new Path2D();
        rectangle.rect(10, 10, 50, 50);
        
        const circle = new Path2D();
        circle.moveTo(125, 35);
        circle.arc(100, 35, 25, 0, 2 * Math.PI);
        
        ctx.stroke(rectangle);
        ctx.fill(circle);
        
      • 使用 svg Paths

        // 先移动到点 (M10 10) 然后再水平移动 80 个单位(h 80),然后下移 80 个单位 (v 80),接着左移 80 个单位 (h -80),再回到起点处 (z)。
        const p = new Path2D("M10 10 h 80 v 80 h -80 Z");
        

    使用样式和颜色

    1. 色彩 Colors

      • ctx.fillStyle = color 设置图形的填充颜色
      • ctx.strokeStyle = color 设置图形轮廓的颜色
      // 这些 fillStyle 的值均为 '橙色'
      ctx.fillStyle = "orange";
      ctx.fillStyle = "#FFA500";
      ctx.fillStyle = "rgb(255,165,0)";
      ctx.fillStyle = "rgba(255,165,0,1)";
      
    2. 设置全局对象的透明度值: ctx.globalAlpha = 0.2; 取值在[0, 1]

      • globalAlpha是让整个画布变的透明了
      • 使用之前save, 使用完成之后restore
    3. 线型 Line styles

      • 影响描边样式的因素

        • strokeStyle
        • lineWidth
        • lineCap 描边断点样式 butt/round/square ...
        • lineJoin 描边拐点类型 milter/round/bevel ...
        • meterLimit
      • ctx.lineWidth = value; 设置线条宽度。

      • ctx.lineCap = type; 设置线条末端样式。 (butt,round 和 square。默认是 butt。)

      • ctx.lineJoin = type; 设定线条与线条间接合处的样式。(round, bevel 和 miter。默认是 miter。)

      • ctx.miterLimit = numberValue; 限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。 (只适用于lineJoin="milter"的情况, 裁掉拐角

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

      • ctx.setLineDash(segments) 设置当前虚线样式。setLineDash([20,30,40]) (20长度实线,30虚线, 40实线)

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

    4. 使用虚线

      • 用 setLineDash 方法和 lineDashOffset 属性来制定虚线样式。setLineDash 方法接受一个数组,来指定线段与间隙的交替;lineDashOffset 属性设置起始偏移量。
    5. 渐变 Gradients

      • 线性渐变: 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(rate, color) rate 值域从 0 到 1, 表示渐变的比例点位
      const linearGradient = ctx.createLinearGradient(0, 0, 150, 150);
      const radialGradient = ctx.createRadialGradient(75, 75, 0, 75, 75, 100);
      
      linearGradient.addColorStop(0, "white");
      radialGradient.addColorStop(1, "black");
      
      ctx.fillStyle = linearGradient;
      
      • gradient.addColorStop(position, color), position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值(如 #FFF,rgba(0,0,0,1),等等)。
    6. 纹理 - 图案样式 Patterns

      • createPattern(image, type) 该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y 和 no-repeat。
      // 创建图案
      const pattern = ctx.createPattern(img, "repeat");
      ctx.fillStyle = pattern;
      ctx.fillRect(0, 0, 150, 150);
      
    7. 阴影 Shadows

      • 横向偏移: shadowOffsetX = float
      • 纵向偏移: shadowOffsetY = float
      • 模糊度: shadowBlur = float
      • shadowColor = color
      const ctx = document.getElementById("canvas").getContext("2d");
      
      ctx.shadowOffsetX = 2;
      ctx.shadowOffsetY = 2;
      ctx.shadowBlur = 2;
      ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
      
      ctx.font = "20px Times New Roman";
      ctx.fillStyle = "Black";
      ctx.fillText("Sample String", 5, 30);
      
    8. ctx.fill('nonzero' | 'evenodd') 填充规则

      • 填充规则根据某处在路径的外面或者里面来决定该处是否被填充

    绘制文本

    1. 文本属性

      • 字体font ctx.font = 'bold 18px serif';
      • 水平对齐
      • 垂直对齐
    2. 绘制文本

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

      • ctx.font = value; 使用和 CSS font 属性相同的语法。默认的字体是 10px sans-serif。
      • ctx.textAlign = value;
      • ctx.textBaseline = value; (top middle bottom hanging alphabetic ideographic)
      • ctx.direction = value;
    4. 预测量文本宽度

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

    使用图片

    1. 引入图像到 canvas 里需要以下两步基本操作:

      • 获得一个指向 HTMLImageElement 的对象或者另一个 canvas 元素的引用作为源,也可以通过提供一个 URL 的方式来使用图片
      • 使用 drawImage()函数将图片绘制到画布上
    2. 绘制图片

      • drawImage(image, x, y, width?, height?) 绘图 + 位移 + 缩放: 在canvas中(x,y)坐标处绘制宽度为width高度为height区域的图片
      • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) 绘图+裁剪+移动+缩放, 用于控制做切片显示的。 后 4 个则是定义切片的目标显示位置和大小。
        • sx: 相机视口位置横向坐标 (相当于画布左侧区域移动了sx) 对图像进行了横向裁剪

        • sy: 相机视口位置纵向坐标 (相当于画布左侧区域移动了sy) 对图像进行了纵向裁剪

        • sWidth: 相机视口的宽度 (将相机视口里的内容放置在渲染区域)

        • sHeight: 相机视口的宽度 (将相机视口里的内容放置在渲染区域)

        • 在画布上放置图像的 dx 坐标位置。

        • 在画布上放置图像的 dy 坐标位置。

        • 要使用的图像的宽度。dWidth(伸展或缩小图像)

        • 要使用的图像的高度。dHeight(伸展或缩小图像)

    3. 缩放时启用平滑缩放

      ctx.mozImageSmoothingEnabled = false;
      ctx.webkitImageSmoothingEnabled = false;
      ctx.msImageSmoothingEnabled = false;
      ctx.imageSmoothingEnabled = false;
      

    变形 transformations

    1. 状态的保存和恢复

      • ctx.save(); ,每当 save()方法被调用后,当前的状态就被推送到栈中保存。
        • 当前应用的变形(即移动,旋转和缩放,见下)
        • 以及下面这些属性:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled
        • 当前的裁切路径(clipping path)
      • ctx.restore();
      • 可以调用任意多次 save 方法。每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。
    2. 移动 Translate (将画布进行移动)

      • translate(x, y) 方法接受两个参数。x 是左右偏移量,y 是上下偏移量
      function draw() {
        let ctx = document.getElementById("canvas").getContext("2d");
        for (let i = 0; i < 3; i++) {
          for (let j = 0; j < 3; j++) {
            ctx.save();
            ctx.fillStyle = "rgb(" + 51 * i + ", " + (255 - 51 * i) + ", 255)";
            ctx.translate(10 + j * 50, 10 + i * 50);
            ctx.fillRect(0, 0, 25, 25);
            ctx.restore();
          }
        }
      }
      
    3. rotate(Math.PI / 4) ,它用于以原点(0, 0)为中心顺时针旋转 canvas。

    4. scale(x, y) 方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比 1 小,会缩小图形,如果比 1 大会放大图形。默认值为 1,为实际大小。

    5. transform(a, b, c, d, e, f) 将当前的变形矩阵乘上一个基于自身参数的矩阵

      // 如下面的矩阵所示:
      [
         a c   e
         b d   f
         0 0   1
      ]
      a (m11) 水平方向的缩放
      b(m12)  竖直方向的倾斜偏移
      c(m21)  水平方向的倾斜偏移
      d(m22)  竖直方向的缩放
      e(dx)   水平方向的移动
      f(dy)   竖直方向的移动
      
      • setTransform(a, b, c, d, e, f)
      • resetTransform() 重置当前变形为单位矩阵,它和调用以下语句是一样的:ctx.setTransform(1, 0, 0, 1, 0, 0);

    组合 Compositing

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


      image.png
    2. 路径裁切 clip() 将当前正在构建的路径转换为当前的裁剪路径。

      • 状态save
      • 定义路径
      • clip
      • 绘制其他图形 (之后绘制的图形只显示在这个路径之中)
      • 状态restore (用完路径裁剪之后, 仍然想绘制其他的话)

    像素操作

    1. ImageData 对象

      • data:Uint8ClampedArray [r,g,b,a, r,g,b,a, r,g,b,a, ...]

      • width 图片宽度,单位是像素

      • height 图片高度,单位是像素

      • data Uint8ClampedArray 类型的一维数组,包含着 RGBA 格式的整型数据,范围在 0 至 255 之间(包括 255)。data 属性返回一个 Uint8ClampedArray,它可以被使用作为查看初始像素数据。每个像素用 4 个 1bytes 值 (按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。每个颜色值部份用 0 至 255 来代表。

      • Uint8ClampedArray 包含高度 × 宽度 × 4 bytes 数据,索引值从 0 到 (高度 × 宽度 ×4)-1

      // 要读取图片中位于第 50 行,第 200 列的像素的蓝色(0=R.1=G,2=B)部份
      blueComponent = imageData.data[50 * (imageData.width * 4) + 200 * 4 + 2];
      
      // 根据行、列读取某像素点的 R/G/B/A 值的公式:
      imageData.data[50 * (imageData.width * 4) + 200 * 4 + 0 / 1 / 2 / 3];
      
      // 使用 Uint8ClampedArray.length 属性来读取像素数组的大小(以 bytes 为单位):
      const numBytes = imageData.data.length;
      
    2. 创建 ImageData 对象

      • const myImageData = ctx.createImageData(width, height); 创建了一个新的具体特定尺寸的 ImageData 对象。所有像素被预设为透明黑。
      • const myImageData = ctx.createImageData(anotherImageData); 创建一个被 anotherImageData 对象指定的相同像素的 ImageData 对象。这个新的对象像素全部被预设为透明黑。这个并非复制了图片数据。
    3. 得到场景像素数据

      • const myImageData = ctx.getImageData(left, top, width, height);
    4. 在场景中写入像素数据

      • ctx.putImageData(myImageData, dx, dy, x,y,w,h); dx 和 dy 参数表示您希望在场景内左上角绘制的像素数据所得到的设备坐标。 x,y,w,h表示选取相对图片位置的坐标取宽度为w高度h的区域渲染
      const invert = function () {
        ctx.drawImage(img, 0, 0);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        for (let i = 0; i < data.length; i += 4) {
          data[i] = 255 - data[i]; // red
          data[i + 1] = 255 - data[i + 1]; // green
          data[i + 2] = 255 - data[i + 2]; // blue
        }
        ctx.putImageData(imageData, 0, 0);
      };
      
    5. 缩放与反锯齿

      • 反锯齿默认是启用的,关闭它以看到清楚的像素。可以通过切换 imageSmoothingEnabled 属性查看不同的效果(不同浏览器需要不同前缀)。
    6. 保存图片

      • canvas.toDataURL('image/png')
      • canvas.toDataURL('image/png', quality); quality 提供从 0 到 1 的品质量,1 表示最好品质,0 基本不被辨析但有比较小的文件大小。
      • canvas.toBlob(callback, type, encoderOptions) 创建了一个在画布中的代表图片的 Blob 对像。

    相关文章

      网友评论

          本文标题:2022-08-28 canvas 学习笔记

          本文链接:https://www.haomeiwen.com/subject/hcyqnrtx.html