canvas学习二

297 阅读4分钟

一、绘制文字

【1】font字体属性

canvas 里的font 属性和css 的font 属性是一样的,它可以设置文本的粗细、字号、字体等

  • css 设置字体:p{ font: bold 15px  微软雅黑; }
  • canvas 设置字体:ctx.font = 'bold 15px  微软雅黑'

【2】textAlign水平对齐

textAlign 设置或返回文本内容的当前对齐方式 

  • start: 默认, 文本在指定的位置开始
  • end: 文本在指定的位置结束
  • center: 文本的中心被放置在指定的位置
  • left: 文本左对齐
  • right: 文本右对齐

【3】textBaseline垂直对齐

textBaseline 设置或返回在绘制文本时使用的当前文本基线

  • alphabetic:默认,文本基线是普通的字母基线
  • top:文本基线是 em 方框的顶端
  • hanging:文本基线是悬挂基线
  • middle:文本基线是 em 方框的正中
  • ideographic: 文本基线是 em 基线
  • bottom:文本基线是 em 方框的底端

【4】文本绘制方法

填充文字: fillText(text, x, y, maxWidth)

描边文字: strokeText(text, x, y, maxWidth)

解释:

text:填充的文字

x y:坐标

maxWidth:文字最大宽度,该值小于文字宽度会自动缩小填充文字

【5】获取文字宽度方法

获取文字宽度:ctx.measureText(text)

【6】案例

<body>
  <canvas id="canvas"></canvas>
  <script>
    // 创建canvas
    const canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    const ctx = canvas.getContext('2d');

    // 文字属性
    ctx.font = 'bold 200px Arial';

    // 投影
    ctx.shadowColor = 'rgba(0,0,0,0.6)';
    ctx.shadowOffsetY = 2;
    ctx.shadowBlur = 4;

    // 实体文字
    ctx.fillStyle = '#b76251';
    ctx.fillText('canvas', 50, 150);

    // 实体描边文字
    ctx.strokeStyle = '#f0d5bc';
    ctx.lineWidth = 9;
    ctx.strokeText('canvas', 50, 150);

    // 虚线描边
    ctx.strokeStyle = '#000';
    ctx.lineWidth = 1;
    ctx.setLineDash([5, 3]);
    ctx.strokeText('canvas', 50, 150);
  </script>
</body>

二、绘制图片

【1】绘制图像的基本方式(绘图+位移)

语法:ctx.drawImage(img, x,y)

参数说明:

img:是绘制图片的dom对象

x y :图片向右和向下位移坐标

【2】绘图+位移+宽高

语法:ctx.drawImage(img,x,y,width,height)

参数说明:

img:是绘制图片的dom对象

x y :图片向右和向下位移坐标

width:绘制图片的宽度

height:绘制图片的高度

【3】绘图+位移+宽高+裁剪

语法:ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height)

参数说明:

img:是绘制图片的dom对象

sx sy: 裁剪的左上角坐标

swidth:裁剪图片的高度

sheight:裁剪的高度

x y :图片向右和向下位移坐标

width:绘制图片的宽度

height:绘制图片的高度

【4】JavaScript建立图像源的方式

// 第一种
var img = document.getElementById('imgId');

// 第二种
let img = new Image(); //这个就是img标签的dom对象
img.src = '/images/test.gif';
img.alt = '文本信息';
img.onload = function() {
  //图片加载完成后,执行此方法
};

【5】案例

<body>
  <canvas id="canvas"></canvas>
  <script>
    // 创建画布
    const canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    const ctx = canvas.getContext('2d');

    // 创建图像源
    const img = new Image();
    img.src = './images/person.png';
    img.onload = function () {
      const { width, height } = img;

      // 绘图+移动 drawImage(img, x, y)
      // ctx.drawImage(img, 0, 0);

      // 绘图+移动+宽高 drawImage(img, x, y, width, height)
      ctx.drawImage(img, 0, 0, width / 5, height / 5); //偏移到x轴为0 y轴为0的位置展示, 图片宽高=原图宽高/5

      // 绘图+裁剪+移动+宽高 drawImage(img, sx, sy, swidth, sheight, x, y, width, height)
      ctx.drawImage(
        img,
        0, 0, width / 2, height / 2,  // 从左边 0,0 开始裁剪, 裁剪原图宽度的一半,高度的一半
        200, 0, width / 5, height / 5 // 偏移到x轴200y轴0的位置展示, 图片宽高=原图宽高/5
      );
    };
  </script>
</body>

三、像素操作

【1】imageData是什么?

ImageData 是图片的数据化,是一个对象,它具备以下几个属性:

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

width:整数,ImageData的宽度

heidth:整数,ImageData的高度

Uint8ClampedArray 翻译过来是 8位无符号整型固定数组,每四个数组元素代表了一个像素点的rgba信息,每个元素数值取值范围是[0,255]。若小于0,则为0,大于255,则为255。若为小数,则取整,取整的方法是银行家舍入。

【2】获取imageData对象

方法:ctx.getImageData(x, y, width, height)

作用: 用来获取canvas画布上指定矩形区域的像素数据

解释:

xy: 矩形的左顶点横纵坐标

width: 矩形的宽度

height: 矩形的高度

【3】imageData可以做什么?

我可以通过不同的算法,对ImageData 中的像素进行不同的处理。比如调整图片的色调,检测图像边缘,实现艺术效果,马赛克,人脸识别……

【4】案例

遍历图片像素,通过灰度算法对图片像素做处理使图片变成灰色调

<body>
  <canvas id="canvas"></canvas>
  <script>
    // 创建画布
    const canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    const ctx = canvas.getContext('2d');

    // js创建图片源
    const img = new Image();
    img.src = 'https://img-blog.csdnimg.cn/20210407160120758.png'
    img.setAttribute('crossOrigin', '');
    img.onload = draw;

    function draw() {
      // 图像尺寸
      const { width, height } = img;

      // 在canvas 中绘制图像
      ctx.drawImage(img, 10, 10, 150, 200);

      // 从canvas 中获取图像的ImageData
      const imgData = ctx.getImageData(0, 0, width, height);
      const data = imgData.data;

      // 像素遍历
      for (let i = 0; i < data.length; i += 4) {
        const [r, g, b] = [
          data[i],
          data[i + 1],
          data[i + 2],
        ]

        // 将图片变灰,灰度算法公式: 0.299*r+0.587*g+0.114*b 
        const lm = 0.299 * r + 0.587 * g + 0.114 * b;
        data[i] = lm;
        data[i + 1] = lm;
        data[i + 2] = lm;
      }

      // 在canvas 中显示ImageData
      ctx.putImageData(imgData, 0, 0);
    }

  </script>
</body>

四、变换

【1】缩放scale()

作用:scale()方法缩放当前绘图,更大或更小

语法:ctx.scale(scalewidth,scaleheight)

scalewidth : 缩放当前绘图的宽度 (1=100%, 0.5=50%,2=200%,依次类推)

scaleheight : 缩放当前绘图的高度 (1=100%,0.5=50%,2=200%,依次类推) 

注意:缩放的是整个画布,缩放后,继续绘制的图形会被放大或缩小

【2】位移translate()

语法:ctx.translate(x, y)

x: 添加到水平坐标(x)上的值

y: 添加到垂直坐标(y)上的值

注意:发生位移后,相当于把画布的 0,0 坐标 更换到新的 x,y 的位置,所有绘制的新元素都被影响。位移画布一般配合缩放和旋转等。

【3】旋转rotate()

作用:方法旋转当前的绘图

语法:context.rotate(angle)

angle:弧度(PI)

注意:参数是弧度(PI),如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算

【4】绘制环境保存和还原

ctx.save() 保存当前环境的状态,可以把当前绘制环境进行保存到缓存中

ctx.restore() 恢复之前保存过的路径状态和属性,获取最近缓存的 ctx,一般配合位移画布使用

一般在我们绘制具备同一种样式的图形时,都会用save() restore() 将其包裹起来。这是为了避免当前的图形样式影响以后的图形样式。

【5】案例

<body>
  <canvas id="canvas"></canvas>
  <script>
    // 创建画布
    const canvas = document.getElementById('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    const ctx = canvas.getContext('2d');

    // 缩放: scale(x,y)
    ctx.save()
    ctx.scale(2, 2); // 放大到200%
    ctx.fillRect(0, 0, 100, 100);
    ctx.restore()

    // 移动: translate(x,y)
    ctx.save()
    ctx.translate(250, 0); // 移动到x轴为250和y轴都为0的位置
    ctx.fillRect(0, 0, 100, 100);
    ctx.restore()

    // 旋转: rotate(angle)
    ctx.save()
    ctx.rotate(Math.PI / 4);
    ctx.fillRect(300, 0, 100, 100);
    ctx.restore()
  </script>
</body>