Canvas 中的“无字天书”

Canvas 基础图形

直线图形

html 复制代码
<canvas ref="cnv" width="200" height="150" style="border: 1px dashed gray"></canvas>

注:

  1. 本篇文章所有 JavaScript 都是用的 Vue3 的 setup 格式代码,目的是熟悉巩固 Vue3 的知识点。所有的绘图操作也将在 <canvas> 标签中进行,故只写这一次 HTML 代码。
  2. Canvas 上下文调用方法的参数默认都是以 px 为单位的。

直线

Canvas 坐标系

Canvas 坐标系遵从的是 W3C 坐标系,跟我们常见的数学坐系唯一不同的是,Y 轴方向的正方向向下

直线的绘制

在 Canvas 中, 我们用 moveTo() 和 lineTo() 这两个方法来配合画直线。

context.moveTo(x1, y1); // 表示直线起点坐标 (x1, y1);

context.lineTo(x2, y2); // 表示终点坐标(x2, y2)

context.stroke(); // 连线

跟我们平时画线的过程是一样的,先确定两点,然后再连线。

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    // cnv.value 类似于 document.getElementById() 获取的 canvas 对象
    const ctx = cnv.value.getContext("2d");

    ctx.moveTo(40, 30);
    ctx.lineTo(160, 30);
    // 多条直线
    ctx.moveTo(40, 90);
    ctx.lineTo(160, 90);
    // 相连的直线
    ctx.lineTo(160, 60);
    ctx.stroke();
  })
</script>

这是一段 Vue3 的代码,我们重点关注 moveTo 和 lineTo 方法。当 moveTo多次调用的时候,画笔抬起,重新找到起始点。当起始点与上一条直线的终点相同的时候,那么接下来的画线则与上一条直线相连接,那么要画个图形就很简单了,不必赘述了。

矩形

之前我们画矩形是通过 moveTo 和 lineTo 方法来 画的,一个矩形四个点,就要调用三次 lineTo 方法,这样是否有感觉到一丝繁琐,对于程序员来说,重复的操作是否你总是想把这些重复的操作归纳一下,通过函数来一次性处理,或者统一处理,如果你还没有这样的意识,可能需要在开发学习中要多归纳整理了。当然,画矩形,自然也是提供了 strokeStyle 属性 和 strokeRect() 方法进行处理的。

1. strokeStyle 属性

strokeStyle 属性的取值有 3 种, 颜色值、渐变和图案,也就是绘制矩形边线的颜色取值。渐变和图案暂时先不作讲解,先来看一看颜色值的取值可以是十六进制颜色值、颜色关键字、rgb/rgba格式颜色值。

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    const ctx = cnv.value.getContext("2d");

    // 以蓝色为例
    ctx.strokeStyle = '#0000FF'; // 十六进制
    ctx.strokeStyle = 'blue'; // 颜色关键字
    ctx.strokeStyle = 'rgb(0, 0, 255)'; // rgb 格式颜色
    ctx.strokeStyle = 'rgba(0, 0, 255, 1.0)'; // rgba 格式颜色
  })
</script>

2. strokeRect() 方法

我们选好了用什么颜色的🖌,那么,就可以画矩形了吧? 但是我们是不是还需要从哪里开始画,是不是可以联想到之前的 moveTo 方法?然后要画多大的矩形?这就是我们 strokeRect() 方法,一步就可以办到,我们来认识一下 strokeRect() 方法。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> c t x . s t r o k e R e c t ( s t a r t P o i n t X , s t a r t P o i n t Y , R e c t W i d t h , R e c t H e i g h t ) ctx.strokeRect(startPointX, startPointY, RectWidth, RectHeight) </math>ctx.strokeRect(startPointX,startPointY,RectWidth,RectHeight)

从上述式子里边可以很清楚的看到,前两个参数直接定位到开始起笔的点,后面两个参数也就是矩形的长宽,这样一看是不是画个矩形很简单了啊。来看个例子。

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    const ctx = cnv.value.getContext("2d");

    ctx.strokeStyle = '#0000FF'; // 十六进制
    // 从点(20, 20)起笔,画出长宽都为60的矩形
    ctx.strokeRect(20, 20, 60, 60);
  })
</script>

这样我们就画出了一个蓝色的正方形,如果先画再选颜色可以吗?画是能画,但是颜色就不是蓝色啦,除非再涂一遍,哈哈。

填充矩形

1. fillRect() 方法

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> c t x . f i l l R e c t ( s t a r t P o i n t X , s t a r t P o i n t Y , R e c t W i d t h , R e c t H e i g h t ) ctx.fillRect(startPointX, startPointY, RectWidth, RectHeight) </math>ctx.fillRect(startPointX,startPointY,RectWidth,RectHeight)

我不仅想要带颜色的边框矩形,我还想在矩形中涂上颜色。来看看 fillRect() 方法 和 fillStyle 属性。fillStyle 属性 与 strokeStyle 属性的取值,fillRect() 方法与 strokeRect() 方法调用参数 都是异曲同工。直接来看例子:

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    const ctx = cnv.value.getContext("2d");

    ctx.strokeStyle = '#0000FF'; // 十六进制
    // 从点(20, 20)起笔,画出长宽都为60的矩形
    ctx.strokeRect(20, 20, 60, 60);
    
    // 以蓝色0.3的透明度来区分 边线颜色与填充颜色
    ctx.fillStyle = 'rgba(0, 0, 255, 0.4)';
    ctx.fillRect(20, 20, 60, 60);
  })
</script>

2. rect() 方法

飞鸽传输的密信,我们在武侠剧中常常可以看到,一封无字天书,经过特殊处理后,字就显示出来了,那么,无字天书是怎么"写"成呢?

那就是用了我们的 rect() 方法,我们来一探究竟。

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    const ctx = cnv.value.getContext("2d");

    ctx.strokeStyle = '#FF0000'; // 十六进制
    // 以蓝色0.3的透明度来区分 边线颜色与填充颜色
    ctx.fillStyle = 'rgba(255, 0, 0, 0.3)';
    
    ctx.rect(40, 40, 60, 60); // 此时就是无字天书
    
    // 收到密信的人,用 fill() 和 stroke() 这两种秘法来让无字天书展示真正的内容
    ctx.stroke();
    ctx.fill();
  })
</script>


<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> c t x . r e c t ( s t a r t P o i n t X , s t a r t P o i n t Y , R e c t W i d t h , R e c t H e i g h t ) ctx.rect(startPointX, startPointY, RectWidth, RectHeight) </math>ctx.rect(startPointX,startPointY,RectWidth,RectHeight)

从上面的例子中我们明白了,rect() 我们可以把它理解为其实画了,只是没有用秘法看不到而已,也就是 rect() 绘制的图形必须使用 (描边) stroke() 或者 (填充) fill() 方法才能显示出来。

清空矩形

在 Canvas 中,我们使用 clearRect() 来当橡皮檫,而且是带科技的橡皮檫,它可以清空"指定的矩形区域"。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> c t x . c l e a r R e c t ( s t a r t P o i n t X , s t a r t P o i n t Y , R e c t W i d t h , R e c t H e i g h t ) ctx.clearRect(startPointX, startPointY, RectWidth, RectHeight) </math>ctx.clearRect(startPointX,startPointY,RectWidth,RectHeight)

我们来看个例子,我们把刚刚的矩形左上角擦掉 1/4:

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    const ctx = cnv.value.getContext("2d");

    ctx.strokeStyle = '#0000FF'; // 十六进制
    // 以蓝色0.3的透明度来区分 边线颜色与填充颜色
    ctx.fillStyle = 'rgba(0, 0, 255, 0.4)';
    
    ctx.rect(20, 20, 60, 60); // 此时就是无字天书
    
    // 收到密信的人,用 fill() 和 stroke() 这两种秘法来让无字天书展示真正的内容
    ctx.stroke();
    ctx.fill();
    
    ctx.clearRect(19, 19, 31, 31);
  })
</script>

清空 1 / 4 的区域,怎么不是 ctx.clearRect(20, 20, 30, 30) 呢?那我们就得注意了,我们在绘制矩形的时候,是有描边的,stroke(),strokeRect() 方法,描边默认是宽度1px,但是我们看到的描边,感觉不像是1 px,更像是2 px,是的,就是2px。这里我们后边的文章再做详细解释,我们现在暂时就将清空起点左上各平移1px,宽高加1px来处理。

清空画布

有了这个清空矩形区域的方法,那我是否可以考虑,我要清空整个画布,要重新作画该怎么处理呢?

vue 复制代码
<script setup>
  import {ref, onMounted} from 'vue';
  const cnv = ref();

  onMounted(() => {
    const ctx = cnv.value.getContext("2d");

    ctx.strokeStyle = '#0000FF'; // 十六进制
    // 以蓝色0.3的透明度来区分 边线颜色与填充颜色
    ctx.fillStyle = 'rgba(0, 0, 255, 0.4)';
    
    ctx.rect(20, 20, 60, 60); // 此时就是无字天书
    
    // 收到密信的人,用 fill() 和 stroke() 这两种秘法来让无字天书展示真正的内容
    ctx.stroke();
    ctx.fill();
    
    // 清空画布,矩形的宽高就等于画布的宽高, 起点从原点开始
    ctx.clearRect(0, 0, cnv.value.width, cnv.value.height);
  })
</script>

清空画布:矩形的宽高就等于画布的宽高, 起点从原点开始

总结

  • Canvas 上下文调用方法的参数默认都是以 px 为单位的;
  • Canvas 中目前学到的方法 stroke(), fill() 方法;
  • 直线涉及属性与方法:moveTo, lineTo;
  • 相连直线:起始点坐标等于上一条线结束点坐标。
  • 矩形涉及属性与方法:strokeStyle,strokeRect(), fillStyle, fillRect(), rect(), clearRect();
  • 清空画布,起点就是原点,矩形的宽高就等于画布的宽高。
相关推荐
J总裁的小芒果12 分钟前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript
Lei_zhen9614 分钟前
记录一次electron-builder报错ENOENT: no such file or directory, rename xxxx的问题
前端·javascript·electron
咖喱鱼蛋17 分钟前
Electron一些概念理解
前端·javascript·electron
yqcoder18 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
鑫宝Code35 分钟前
【React】React Router:深入理解前端路由的工作原理
前端·react.js·前端框架
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
永乐春秋3 小时前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿3 小时前
【前端】CSS
前端·css
ggdpzhk3 小时前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
学不会•5 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html