• 初识canvas(二)


    上节文章中,给大家分享了canvas最基础的用法,包括绘制线条、控制渲染方式、绘制图形、作用域、添加阴影、清理、剪切等功能,本节将继续为大家分享canvas的基础用法,同时也是最后一节基础知识分享,之后的内容,我们将会进入到对webgl的分享中。

    1. 文本绘制

    首先我们要提到的是绘制文本,在canvas 的开发过程中,文本的内容是肯定会存在的。本小节就来给大家分享下如何渲染文本。

    1.1 绘制空心和实心文本

    canvas中提供了两种绘制文本的方法,分别是绘制实心文本和空心文本,它们的方法分别是:

    • strokeText(text, x, y, maxWidth): 绘制空心文本
    • fillText(text, x, y, maxWidth): 绘制实心文本

    参数介绍:

    • text: 要绘制的文本内容
    • x, y: 坐标点,文本左上角的坐标点
    • maxWidth: 允许渲染的最大像素宽度

    栗子:

    // 绘制实心文本
    c.fillText('hello world', 100, 100); // 将 hello world 这个内容从 100 100 这个点开始渲染。
    
    // 绘制空心文本
    c.strokeText('hello world', 200, 200); 
    

    如果这里你的字体是默认大小,可能会看不到空心效果。改变字体大小在下文中有分享到。

    1.2 改变文本样式

    如果我们想修改字体的颜色,可以根据 绘制图形 一节中的方法,使用 strokeStyle、fillStyle 来修改。

    1. 要设置实心文本字体为蓝色
    c.fillStyle = 'blue';
    c.fillText('hello world', 100, 100);
    
    2. 要设置空心字体为红色
    c.strokeStyle = 'yellow';
    c.strokeText('hello world', 200, 200);
    

    1.3 改变文本大小和字体样式

    修改字体大小和字体样式需要用到 font = '字体大小 字体样式’ 属性。

    如:把字体改为 宋体 40px

    c.font = '40px 宋体';
    

    如果是特殊的字体,会出现不支持的现象。

    1.4 修改文本对齐方式

    文本对齐方式分为 垂直水平 对齐方式。

    1. 垂直方向对齐。

    这里需要用到 textBaseLine 这个属性。意为按照基线对齐。它有6个值,分别是:

    • alphabetic: 默认值,意为普通的字母基线。可理解为四线三格的第三条线。
    • top:文字头部对齐基线
    • hanging:悬挂基线,与top稍有不同
    • middle:文字中部对齐
    • ideographic:表意基线。稍难理解,可看示意图
    • bottom:文字底部对齐基线

    示例:

    // 首先我们画一条基准线,让文字按照这条线对齐
    c.strokeStyle = 'blue';
    c.moveTo(5, 100);
    c.lineTo(700, 100);
    c.stroke();
    
    c.font = '20px 宋体';
    
    // 枚举可用的对齐方式。
    c.textBaseline = 'top';
    c.fillText('Top', 5, 100);
    c.textBaseline = 'bottom';
    c.fillText('Bottom', 100, 100);
    c.textBaseline = 'middle';
    c.fillText('Middle', 200, 100);
    c.textBaseline = 'alphabetic';
    c.fillText('Alphabetic', 300, 100);
    c.textBaseline = 'hanging';
    c.fillText('Hanging', 400, 100);
    c.textBaseline = 'ideographic';
    c.fillText('ideographic', 500, 100);
    

    示例图:

    2. 水平居中

    水平居中需要使用 textAlign 属性。同样也是基于基准线对齐,有5个属性值。

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

    栗子:

    // 创建基准线
    c.strokeStyle = 'blue';
    c.moveTo(150, 20);
    c.lineTo(150, 400);
    c.stroke();
    
    c.font = '30px 宋体';
    
    // 枚举可用的对齐方式。
    c.textAlign = 'start';
    c.fillText('start', 150, 50);
    c.textAlign = 'end';
    c.fillText('end', 150, 100);
    c.textAlign = 'left';
    c.fillText('left', 150, 150);
    c.textAlign = 'center';
    c.fillText('center', 150, 200);
    c.textAlign = 'right';
    c.fillText('right', 150, 250);
    

    示例图:

    3. 不固定宽高的画布水平居中

    对于宽度不固定的画布,我们使用 textAlign 的作用就不太大了。因为此时我们需要根据画布的宽度进行实时计算。此时我们需要获得两个数值。画布宽度和字体宽度。画布宽度比较简单,使用 ctx.width 就可以获取。

    字体的宽度。需要用到 measureText(text) 方法。此方法可根据你设置的字体大小来返回传入文本的像素宽度。

    栗子:

    c.font = '20px 宋体'
    const textData = c.measureText('hello world');
    console.log(textData.width) // 84
    

    设置字体宽度为 20px ,则渲染后的 hello world 占据的像素宽度为 84px(不同浏览器之间会有差异)

    这样我们就可以得到水平居中的计算方式

    文本x坐标 = (画布宽 - 文本宽)/ 2

    const x = (ctx.width - c.measureText('hello world')) / 2;
    

    2. 动画

    2.1 状态保存与恢复

    分享动画之前 ,我们先来介绍 save 和 restore 这两个方法。因为我们在处理动画的过程中,避免不了对画布进行旋转、平移和缩放的操作。从而导致之前或之后的绘制出现错乱。而``save 和 restore` 这两个方法就可以避免这个问题。

    • save: 保存当前canvas的状态。

    • restore: 恢复之前保存的状态。

    2.2 变换

    说到动画,无非就是对图形的旋转、缩放、平移这几项内容。canvas 中提供了一系列的方法。

    • translate(x, y): 平移。可改变当前画布的原点位置。
    • rotate(deg) :旋转。其中 deg 代表的是弧度制。(角度转弧度请看初始canvas(一)的内容)
    • scale(x,y): 缩放,x代表x轴缩放。y代表y轴缩放。

    栗子:

    // 原始矩形
    c.save()
    c.fillRect(10, 10, 100, 100);
    c.restore()
    
    // 平移50px
    c.save()
    c.translate(50, 50);
    c.fillRect(10,10,100,100);
    c.restore()
    
    // 旋转45度
    c.save()
    c.rotate(45 * Math.PI / 180);
    c.fillRect(210, 110, 100, 100)
    c.restore()
    
    // x轴缩放0.5 y轴缩放1.1
    c.save()
    c.scale(0.5, 1.1)
    c.fillRect(410, 210, 100, 100)
    c.restore()
    

    注意:translate 平移之后是可以改变画布原点的位置的,此时如果我们需要让某个图形围绕自身旋转,则需要将图像的中心点位于画布圆点上。如下方代码所示:

    // 将画布中心移入到 50,50 这个点
    c.translate(50, 50);
    setInterval(() => {
      // 每次绘制之前先清空画布,这里的原点已经在50,50这个位置了。所以需要从 -50这里开始清理。
      c.clearRect(-50, -50, ctx.width, ctx.height);
      // 每次旋转 1 度
      c.rotate(Math.PI / 180);
      // 绘制实心矩形。
      c.fillRect(-25,-25, 50,50);
    }, 16)
    

    这里就可以得到一个围绕自身旋转的实心矩形。

    2.3 transform 矩阵操作

    方法接收 6 个参数。transform(a,b,c,d,e,f)

    其中,

    • 平移:涉及到 e, f 两个参数

    • 缩放:涉及到 a, d 两个参数

    • 拉伸:涉及到 b, c 两个参数

    • 旋转:涉及到 a, b, c, d 四个参数

    此方法在后续的讲解中还会出现,并且方法不太好理解,这里只简单说明。不做过多介绍。

    3. 渐变

    本小节来说下如何给图形添加渐变色。渐变色也是我们经常可以用到的功能。添加渐变色我们需要用到下面这两个方法

    • createLinearGradient(sx,sy,ex,ey) 经向渐变
    • createRadialGradient (sx,sy,sr,ex,ey,er) 环形渐变

    sx, sy, sr 代表的是起始点渐变圆的原点坐标和半径ex, ey, er 代表的是终止点渐变圆的原点坐标和半径。渐变方法返回一个对象。我们可以使用这个返回对象的 addColorStop(position, color)方法 执行添加颜色的操作。

    position表示渐变的百分比,也就是渐变的位置。值是0-1 之间的浮点数。

    color是要添加的颜色

    下面,我们通过一个栗子来看下如何创建渐变图形。

    栗子1 -- 径向渐变:

    // 创建径向渐变,得到渐变对象。
    const lg = c.createLinearGradient(10, 10, 200, 200);
    // 通过渐变对象来添加颜色
    lg.addColorStop(0,"black");
    lg.addColorStop(1, 'orange');
    
    // 将得到的渐变色添加到填充样式中。
    c.fillStyle = lg;
    c.fillRect(100, 100, 200, 200);
    

    栗子2 -- 环形渐变:

    // 起始点和终止点圆心坐标相同,代表从同一点开始散发
    const lg = c.createRadialGradient(150, 100, 5, 150, 100, 100);
    lg.addColorStop(0,"black");
    lg.addColorStop(1, 'orange');
    
    c.fillStyle = lg;
    c.arc(150, 100, 100, 0, 2 * Math.PI);
    c.fill();
    

    渐变示意图:

    4. 源目标和透明度

    4.1 透明度设置

    对于透明度设置我们只需要知道一个属性就可以。

    • globalAlpha = value: value 的取值范围在 0-1 之间。代表当前画布的透明度是多少。

    4.2 源目标设置

    源与目标设置我们需要用到 globalCompositeOperation 这个属性,它有N 个属性值。这里我们就不一一介绍了,这里我们先绘制一个红色的矩形,再绘制一个蓝色的矩形,然后我们来看下设置不同的globalCompositeOperation会出现什么情况。

    图解:

    有需要的话可根据上图进行筛查,看下自己需要哪种效果。对应设置。

    5. 图片绘制和背景设置

    5.1 图片绘制

    对于图片的操作在日常的工作中肯定会经常用到。canvas 中也提供了对于图片操作的方法供开发人员使用。

    注意:
    在加载图片的时候,一定要确保的是要在图片加载完成之后再添加到画布中。因此可以给图片使用onload事件。

    如:

    const image = new Image();
    image.onload = function () {
      // 绘制图片操作
    }
    image.src = '图片链接';
    

    接下来绘制图片的方法默认都是存在于 onload 事件中的。

    • drawImage可接收 3,5,9个参数;
      • 三个参数(img,x,y)
        • img是图片对象,x,y是图片在画布中的原点位置
      • 五个参数(img,x,y,imageWidth,imageHeight);
        • 前三个参数不变,imageWidth,imageHeight设置的是图片的宽和高
      • 九个参数(img,x,y,imageWidth,imageHeight,imgx,imgy,imgw,imgh);
        • 前五个参数不改变,imgx,imgy表示从图片的这个点开始取像素。imgw,imgh表示的是取多宽多高的像素。

    5.2 背景设置

    通过createPattern(image, repetition)可以为画布设置背景图像。

    其中, image代表的是图片对象。repetition代表的是是否平铺,repeat:平铺, no-repeat:不平铺

    6. 像素操作

    canvas最引入注目的功能就是对于像素点的操作。这个功能可以让我们实现众多绚丽的特效。希望小伙伴们在领悟了像素操作的真谛之后,也能做出绚丽的特效。这个我们也成为粒子效果;

    对于像素操作,canvas中提供了三个方法。

    • getImageData(x,y,w,h): 获取画布中指定位置的像素集合 前两个参数是你想要获取的原点位置,后两个参数是你想要获取的范围
    • putImageData(data, x,y): 设置画布中指定位置的像素集合,前两个参数是你想要设置的原点位置
    • createImageData(data): 直接生成新的像素矩阵,不用获取

    栗子:

    const data = c.getImageData(0, 0, 10, 10);
    console.log(data);
    /*
    [
    	[1,2,3,4,5,6,7,8,9,10……],
    	…………
    ]
    */
    

    这里我们通过 getImageData 可以获取到一个二维数组,代表获取到的点位图。

    数组中,每四个元素是一组。分别代表 r,g,b,a 中的每一项。每个r,g,b元素的取值范围为 0-255a 的取值范围为0-1;

    如果我们想对像素做操作,那就修改这些值,如图片取反、复古风、底片…………等等,都可以实现。

    有兴趣的小伙伴可以探讨一下哟~

    7. 曲线

    • arcTo(startx, starty, endx, endy, r)
      • 此方法可以让我们创建弧形线条。startx, starty 表示弧的起始点。endx, endy表示弧的终点。r 表示你弧的半径。

    示例:

    c.beginPath()
    c.moveTo(20,20); 
    c.lineTo(100,20);
    c.arcTo(150,20,150,70,10); // 创建弧
    c.lineTo(150,120);
    c.stroke()
    
    • quadraticCurveTo(cox, coy, endx, endy) 二次贝塞尔曲线
      • 贝塞尔曲线可以帮我们获得更加多变的曲线内容。cox, coy 表示控制点坐标。endx, endy 表示结束点坐标。

    示例:

    c.beginPath()
    c.moveTo(20,20);
    // 将控制点设置在线段中间,
    c.quadraticCurveTo(60, 80, 100, 20)
    c.stroke()
    

    示例图:

    除了这两种曲线,还有三次贝塞尔曲线。小伙伴们可以自己试验下,与二次贝塞尔曲线不同的是添加了一组控制点。

    8. 事件

    作为canvas中唯二的两个可以获取到当前图形信息的事件。isPointInPath和isPointInStroke的作用不可小觑。在很多针对图形的操作我们都需要用到这个方法。

    方法也是比较简单。

    • isPointInPath(x, y) 接收两个参数,一个x坐标 一个y坐标,判断当前坐标是否在图形之内
    • isPointInStroke(x, y) 接收两个参数,一个x坐标 一个y坐标,判断当前坐标是否在空心图形边框上。

    9. 将canvas转换为图片 -- toDataURL

    最后一个来分享下如何将我们绘制好的图形保存下来。对之后的分享自己绘制的图形,在其他内容上显示等等等等,都可以用到。

    canvas转换为图片,我们需要用到 toDataURL(type, encoderOptions)

    type 可以设置我们想得到的类型。如: image/png、image/jpg…………

    encoderOptions 可以设置图片的质量。

    栗子:

    const url = ctx.toDataURL('image/png')
    console.log(url); // data:image/png;base64,……………………
    

    注意:

    这里我们是使用的 ctx 来转换图片,也就是使用 canvas 这个标签对象来转换。

    到这里我们对于 canvas 的基础内容就分享完了,从下节开始,我们就要进入到对 webgl 的学习中了。

    好了,今天的分享就到这里了,Bye~

  • 相关阅读:
    struts2 标签 前台遍历 字符串数组 String[]
    007-服务器域名&上传网站
    006-DOS命令
    005-OSI七层模型&IP地址
    004-编程语言发展史
    003-计量单位
    002-B/S架构&C/S架构
    001-计算机的组成
    1083. List Grades (25)
    1037. Magic Coupon (25)
  • 原文地址:https://www.cnblogs.com/yancyCathy/p/14117086.html
Copyright © 2020-2023  润新知