Canvas 2D几何基础API全解:点、线、面

您所在的位置:网站首页 美的毛笔字书写视频 Canvas 2D几何基础API全解:点、线、面

Canvas 2D几何基础API全解:点、线、面

2023-11-22 08:38| 来源: 网络整理| 查看: 265

前言

看过很多Canvas教程,却一看就忘,就和没看过一样。这里笔者以点、线、面(2D平面)的几何理论作铺垫,层层递进,介绍Canvas的绘图理论以及API调用,看过这篇,就再不担心不会Canvas操作了。

一、点

绘制的一切应该从「点」说起,因为「点形成线,线形成面」,而2D绘图构成的形状(面)无非就是这些东西,

所有形状都是线(直线 + 弧线)的组合 形状有三大特性:填充,描边,特效 一切皆是密集的像素点构成的平面

从上面这三点出发,即涵盖了2D绘图的大部分内涵。

要区别的是,几何上对“点”的描述是“没有面积的”,点的移动轨迹构成一条线,此时线也是没有面积的,因此,要想在终端设备上呈现出人类可见的图形,它必然已经构成了一个面,理解这一点十分重要。

因此,当我们讨论绘制一个(可见的)点时,实则是在绘制一个”实心圆“,其本质是一个面。然而,这种描述并不利于信息的传递或表达。所以,我们需要对“点”的概念做一个界定:

“点”在多数情况下的含义是“实心圆”

做了这个界定,我们再从实践里看Canvas的API。

任何canvas绘图都要先走下面这两步:

// 1. 拿到dom元素 const el = document.getElementById("canvas"); // 2. 拿到绘图上下文 const ctx = el.getContext('2d');

有了绘图上下文,我们即可以开始操作,

// 在(top: 100, left: 100)的位置绘制一个半径为5px的圆 ctx.arc(100, 100, 5, 0, Math.PI * 2); // 指定“填充”属性 ctx.fillStyle = 'red'; // 执行“填充”操作 ctx.fill();

得到下面的结果,

dian.png

注意,canvas的默认宽高是300 * 150px的,这里即在(100,100)的位置画出了一个红色的圆。

其实,canvas画圆的本质并不是画一个圆,而是先画一个圆弧(从0开始,到2 * PI结束,正好是360°),形成一个闭合的形状以后,再对形状用红色填充,这就是我们之前所说的实心圆。

关于arc这个画弧的API,在「线」的部分会再详细说,总之,这呼应了我们在文章开头所说的,canvas本没有点,点就是(圆弧)线围成的实心(填充)圆。

二、线

线分为直线和弧线,弧线又可以分为圆弧和贝塞尔曲线(曲率与圆弧不一致),下面我们一一讲解。

这里特意说明一下,几何上对直线的严格定义是没有两头端点,可以无限延伸的,我们这里所说的直线其实是“线段”(或“弧线段”),所以,我们在讲解的时候要重新定义线的概念,正如(重新定义)“点”一样。

在讲解之前,先说一下moveTo(x, y)这个API,它是指我们把当前绘图笔的焦点移动到某个位置,以这个位置为起点进行线的描绘。这里可能有点抽象,看下面的例子就好。

2.1 直线

直线的API是lineTo(x, y),下面展示一个例子,从(50, 100)画到(100, 100)的一条水平直线,这里再对“直线”对概念界定一下,

从画布上已知坐标的一个点,到另一个已知坐标点连接成的线,并且具有固定的宽度。

下面是实践,

ctx.moveTo(50, 100); ctx.lineTo(100, 100); ctx.lineWidth = 5; ctx.stroke()

结果如下,

zhixian.png

代码的前几行都比较好理解,这里把新出线的API和前面的对比一下,

stoke():描边(边框) fill():填充(内部)

由于直线没有形成一个封闭的形状,而且我们指定的是线的宽度,所以这里我们只能用“描边”的API。

那么这里可不可以用填充的API取代呢,毕竟这个直线看起来也可以形容为一个宽很小的矩形?这个答案我们在“第三节——面”的部分揭晓。

2.2 圆弧线

下面我们该来详细说一下arc这个API了,可以直接看参数的定义,

ctx.arc(x, y, radius, startAngle, endAngle [, counterclockwise]);

我翻译一遍,

ctx.arc(圆心x坐标,圆心y坐标,半径,开始角度,结束角度,可选:是否逆时针)

看一个例子,

ctx.arc(100, 100, 50, 0, Math.PI); ctx.strokeStyle="blue"; ctx.stroke()

结果如下,

clockwise-banyuan.png

因为弧走过的位置是0到Math.PI,所以画了一个180度的半圆。

看看给counterclockwise参数设定为true是怎样?

ctx.arc(100, 100, 50, 0, Math.PI, true);

如下,

counterwise-banyuan.png

这下就变成逆时针画的了!(从右边,逆时针往左上,再到左下)。

2.3 贝塞尔曲线

这个曲线的目的是帮助我们画出自定义曲率的曲线,具体的操作方法稍复杂,这里仅给出MDN的解释,

贝塞尔曲线是一种使用数学方法描述的曲线,被广泛用于计算机图形学和动画中,在 vector images 里,贝塞尔曲线用于定义可无限放大的光滑曲线。

贝塞尔曲线由至少两个控制点进行描述。Web 技术中使用的是三次贝塞尔曲线,即使用四个控制点[P0, P1, P2, P3] 描述的曲线。

ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); // 前四个参数对应两个“控制点”的坐标,后四个参数是终点坐标

看看一个例子,

// 画一个闭合形状 ctx.beginPath(); ctx.moveTo(30, 30); ctx.bezierCurveTo(50, 90, 160,-30, 200, 30); // 曲线 ctx.lineTo(200, 100); ctx.lineTo(30, 100); ctx.closePath(); // 填充 ctx.fillStyle = 'lightcoral' ctx.fill(); // 描边 ctx.lineWidth = 2; ctx.strokeStyle = 'lightblue'; ctx.stroke();  

结果如下,

bezier.pgn

这样,我们就能通过控制点来控制曲线的弧度了。

三、面

在Canvas中,我们可以不绘制图形的边框,而直接绘制一个面吗?当然是可以的。

这里对「面」也做一个界定,数学上的平面也是可以无限延展的,这里我们特指「矩形」,即长方形。

画一个长方形非常简单,操作如下,

// 先调整canvas画布的长宽 el.height = 400; el.width = 400; ctx.fillStyle = "red"; ctx.fillRect(100, 100, 100, 200);

这四个参数的含义分别是(x坐标,y坐标,宽度,高度),这里的坐标特指矩阵左上角的坐标。

结果如下,

rect.png

这就是在canvas里直接绘制一个面的方式了。

现在解答一下在第二节提出的问题,我们怎么通过画一个矩阵的方式,画出一条直线呢?毕竟这里线的本质也是一个面。

其实很简单,只需要设置一个很小的宽度(或高度即可),例如,我们要画出第二节一模一样的直线,只需要这样,

ctx.fillStyle = "black"; ctx.fillRect(50, 100, 50, 5);

从(50,100)的位置画一个长度为50,宽度为5的线,看结果,

rect-line.png

是不是完全一样呢~

四、彩蛋

canvas的基础API,除了可以给画布上添加点、线、面以外,还可以直接添加图片和文字,下面是添加文字的例子,

ctx.fillStyle = "black"; ctx.font = "italic 14pt Arial"; ctx.fillText("hello canvas", 20, 20);

效果如下,

text.png

在canvas里设置线性渐变要用到createLinearGradient和addColorStop两个API,参数如下

ctx.createLinearGradient(x0, y0, x1, y1); gradient.addColorStop(offset, color);

下面是一个实例,

// 设置颜色 const grad = ctx.createLinearGradient(0, 0, 200, 0); grad.addColorStop(0, "lightgray"); grad.addColorStop(0.2, "lightblue"); grad.addColorStop(0.6, "blue"); grad.addColorStop(1, "black"); // 添加颜色 ctx.fillStyle = grad; ctx.fillRect(0,0, 200, 200);

效果如下,

gradient-color.png

结合上面两个例子,我们可以绘制渐变色的文字,将文字的fillStyle改为grad颜色即可~

gradient-text.png

over!

后记

看完这篇文章,有没有感觉对canvas的理解更深一层呢,如果觉得有用的话,就请帮忙点一个赞👍吧~

后续可能会推出更深入的canvas API或者WebGL相关的教程,点击“关注”在第一时间获取最新文章。



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3