Canvas学习笔记

Canvas 学习笔记

Canvas是前端图形化学习的一个重点课题,学好canvas能够从底层更好的理解图形化方面的前端知识,为后续的 Web3D 方向的学习打下良好的基础

在接下来的时间里,我会通过阅读《HTML5 Canvas核心技术 之 图形、动画与游戏开发》这本书来进行Canvas的学习,按照笔者的思路进行代码实践,并将学习中的收获记录出来

你可以通过我的个人博客或者此项目的Wiki文档进行查看

2022-07

2022-07-30

  • 简单例子入门了解

先贴代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>A Simple Canvas Example</title>

<style>
body {
background: #dddddd;
}

#canvas {
margin: 10px;
padding: 10px;
background: #ffffff;
border: thin inset #aaaaaa;
}
</style>
</head>

<body>
<canvas id="canvas" width="600" height="300"> Canvas not supported </canvas>

<script src="index.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
index.js

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

// 设置字体
context.font = "38pt Arial";

/**
* fillText 使用fillStyle来填充文本中的字符
* strokeText 使用strokeStyle来描绘字符的轮廓线
* fillStyle和strokeStyle可以是Css格式的颜色、渐变色或者是图案
* fillText和strokeText的3个变量分别是 1.文本 2.文本横坐标 3.文本纵坐标
*/
context.fillStyle = "cornflowerblue";
context.strokeStyle = "blue";
context.fillText(
"Hello Canvas",
canvas.width / 2 - 150,
canvas.height / 2 + 15
);
context.strokeText(
"Hello Canvas",
canvas.width / 2 - 150,
canvas.height / 2 + 15
);

通过示例代码,我们可以绘制出如下图所示的Canvas图像

代码样例效果图

注释掉fillText和strokeText的代码可以很容易发现它们的作用

注释掉fillText的效果

注释掉strokeText的效果

通过这个例子可以发现Canvas有着有趣且丰富的API提供给开发者,看到图像被绘制在浏览器上的那一刻,是不是有辣么一点激动?那么也开始你的Canvas学习之旅吧

  • Canvas元素的宽高

canvas元素的默认宽高是300*150个屏幕像素,可以通过指定canvas元素上的width和height属性来改变canvas元素的宽高,也可以通过css来改变宽高,但是这两者有区别。

canvas元素有两套尺寸,一个是元素本身的大小,一个是元素绘图表面的大小。通过css改变的是元素本身的大小,而设置canvas元素的宽高,会同时改变元素的本身大小和元素绘图表面的大小。

如果使用css来修改canvas元素的宽高,元素的绘图表面大小和元素大小可能不符合,那么浏览器会对元素的绘图表面进行缩放,来使之符合前者,这样会导致比较奇怪的效果出现。

2022-08

2022-08-29

时隔一个月,我还是回来了。。。今天阅读的是第二章《绘制》,简单记录一下

  • 坐标系统

    默认情况,canvas的左上角为坐标原点,但是可以通过 平移(translate) 旋转(rotate) 缩放(scale) 来对坐标系进行自定义的变化

  • canvas绘制图像的步骤

    • 将图形或者图像绘制到一个无限大的透明位图里面,绘制时候遵循当前描边模式 填充模式 线条样式

      • 如果有阴影效果
        • 将图形或者图像的阴影绘制到另一个位图中,在绘制时候遵循当前绘图环境的阴影设定
        • 将阴影中每一个像素的alpha分量乘以绘图环境的globalAlpha属性值
        • 将绘有阴影的位图与经过剪辑区域剪过的canvas进行图像合成(使用当前的合成模式的参数)
    • 将图形或图像的每一个像素的颜色分量乘以绘图环境的globalAlpha属性值

    • 将绘有图形或图像的位图,合成到当前经过剪辑区域剪切过的canvas位图之上(操作时候采用当前的合成操作符)

      canvas绘制过程

  • 矩形的绘制

    方法 method(x,y,w,h)

    • clearRect 清除

    • strokeRect 描边

    • fillRect 填充

      操作受到绘图环境变量的影响,比如说在绘制前指定lineJoin = 'round'lineWidth可以对矩阵的边角样式和描边的宽度造成影响

  • 颜色和透明度

    • stokeStyle

    • fillStyle

      颜色值: RGB RGBA HSLA HEX 颜色名

  • 渐变色与图案

    • 渐变

      • 线性渐变 linear => createLinearGradient(x,y) => addColorStop(double x,string color)
      • 放射 radial createRadialGradient(x,y) => addColorStop(double x,string color)
    • 图案

      • 图案元素类型:image canvas video
      • 创建方法 createPattern(HTMLImageElement | HTMLCanvasElement | HTMLVideoElement image, DOMString repetition) 第一个参数指定图案所用的图案元素来源,第二个参数取值范围repeat repeat-x repeat-y no-repeat指定了如何重复使用这个图案
  • 阴影

    • 通过这四个值来进行阴影设置

      • shadowColor CSS3格式的颜色
      • shadowOffsetX 阴影的水平像素偏移
      • shadowOffsetY 阴影的垂直像素偏移
      • shadowBlur 一个与像素无关的值,用在高斯模糊的方程中,对阴影进行模糊处理
    • 使用阴影的条件

      • shadowColor的值不是全透明的
      • 其余三个属性中,存在一个非0的值
    • 内嵌阴影

      • shadowOffsetX 和 shadowOffsetY设置为负偏移量可以达到内嵌阴影的效果
    • 性能相关

      • 前面说到,阴影会先渲染到一个辅助位图中,最后这个位图中的内容和屏幕上的canvas图像进行合成,使用了辅助的位图,绘制阴影可能是一项耗时的操作

        如果只是绘制一些简单的图形,大可不必使用阴影效果来增加性能负担

  • 路径,填充和描边

    • stokeRect,fillRect这是立即绘制的,还有一些复杂的图形,比如贝塞尔曲线等都是基于路径的

    • 大多数绘制系统都是基于路径的,比如SVG系统,苹果的Cocoa框架以及Adobe Illustrator等.

    • 使用步骤

      • lineWidth 等描边和填充属性
      • beginPath() 开始一段新的路径
      • rect()arc()方法用于创建矩形和弧形的路径
      • stoke()fill方法,对路径进行描边和填充
      • closePath rect方法所创建的路径是封闭的,而arc方法创建的圆弧路径则不封闭,要封闭某个路径,需要调用closePath()方法
    • 路径与子路径

      • canvas之中只有一条路径存在,Canvas规范将其称为”当前路径”(current path), 但是这条路径却可以包含许多子路径(subpath).

        而子路径,又是由两个或更多的点组成的

      • beginPath会清除前面的子路径的绘制结果

      • 如果连续调用rect => stoke => rect => stoke 那么第二次绘制的时候也会对第一次的结果造成影响

    • 非零环绕规则

      • 当前路径是循环的或者包含多个相交的子路径,那么canvas的绘图环境变量就必须要判断,fill()方法使用的时候,如何对当前路径进行填充.

      • 如何判断由自我交叉的路径?

        • 对于路径中的任意给定区域,从该区域内部画一条足够长的线段,使此线段的终点完全落在路径范围之外

        • 将计数器初始化为0,然后,每当这条线段与路径上的直线或者曲线相交时,就改变计数器的值

          • 如果线段与路径的顺时针部分相交,那么+1
          • 如果线段与路径的逆时针部分相交,那么-1
        • 如果计数器的最终值不是0,那么此区域就不再路径内部,调用fill()时候,浏览器就不会对其进行填充,反之,填充

          非零环绕规则


Canvas学习笔记
https://mengxun1437.github.io/2022/07/30/canvas-learning/
作者
Mengxun
发布于
2022年7月30日
更新于
2022年8月30日
许可协议