Canvas 简单入门小教程

简介: 前端西瓜哥

大家好,我是前端西瓜哥。今天简单说说 Canvas 入门的基础知识。

Canvas 是以 <Cavnas> 作为显示载体,并通过 JavaScript 脚本来绘制位图的技术。

canvas 元素

canvas,画布,这个名字就非常形象,是我们绘制图像的地方。对应的 DOM 元素就是 <canvas>

我们通过 width 和 height 来设置 canvas 元素的宽高。

<canvas width="500" height="500"></canvas>

width 和 height 只支持数字,单位为 CSS 像素值(px),默认值分别为 300 和 150。

如果你提供的是 "100%",它会转换为 100;如果你提供的是非数字,结果就是设置失败,然后拿到默认值。

你可以认为 canvas 获取宽高时进行了类似 parseInt 的处理。

另外,如果你手动修改了 canvas 的宽或高,canvas 的内容会全部清空。

需要特别注意的是,canvas 的宽高不能通过 style 属性来设置。style.widthstyle.height 其实是在设置了宽高的 canvas 上再进行了缩放。某种意义上,你可以把 canvas 元素当作 img 元素。

canvas 的宽高并不是可以设置为无限大的,不同的浏览器允许的最大宽高不同。一旦超过,就会啪地一下变成了 0。一般来说我们没有设置很大的宽高的需求,通常最大为显示屏的宽高就差不多了。

渲染上下文

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

在绘制图形之前,我们需要做一些准备工作,通过 canvas 元素调用 getContext,拿到一个渲染上下文 context。

就好比是拿到只能在特定画布上的画布的画笔。

坐标系

对于计算机来说,坐标系的原点位于屏幕的左上角,向下为 y 轴正方向,向右为 x 轴正方向。

这点和我们学数学坐标系有点不同,要注意一下。

下面我们来看看怎么绘制各种图形。

画个矩形

ctx.fillStyle = '#f04'; // 红色
ctx.fillRect(10 , 10, 200, 100); // 矩形(填充)
ctx.strokeStyle = 'black';
ctx.lineWidth = 4;
ctx.strokeRect(10, 10, 200, 100); // 矩形(描边)

这两个方法都要传入矩形的左上角位置 (10, 10) 和宽高(200 和 100)。

fillRect 用于填充矩形区域,strokeRect 则是描边。

fillStyle 用于设置填充的颜色,strokeStyle 用于设置描边的颜色,lineWidth 只用描边的线宽。

绘制的结果如下:

image.png

可以类比给 Div 元素设置 border 和 background。

Dom 和 Canvas 两种渲染方式的对比

我们不妨将 Cavans 和 Div 展现一个矩形的绘制过程进行对比。

首先,Div 是声明式的,它保留在 Dom 树下,随时可以修改属性,修改后渲染引擎对其进行重新绘制。

而 Canvas 绘制矩形则是命令式的,一旦它被画到画布上,Canvas 就不再管这是不是矩形了,Canvas 只是根据命令画出了一系列像素点,自身并不维护一个被绘制图形形成的树。

如果你要记录曾经画的图形,以及形成的层级,都要开发者自己去维护。

相比 Dom 自动地维护,隐形造成的非必要的回流重绘消耗性能的操作,Canvas 会更原始,把决定是否重绘还是局部冲毁堤岸的权利让渡给开发者,让开发者做性能优化有更大的空间。

但这也让开发者需要做更多的底层基础工作。

绘制圆形

Canvas 并没有提供直接绘制一个圆形的 API,而是提供一个绘制圆弧的 API。

ctx.fillStyle = '#519D36'; // 绿色
ctx.beginPath();
ctx.arc(100, 40, 20, 0, Math.PI * 2); // 0 为从右方为起点,
ctx.fill();
ctx.stroke();

绘制图形通常需要先通过各种 API 描述的子路径组合出一个路径,然后再进行 fill(填充) 和 stroke(描边)。arc 方法就是其中一种描述子路径的 API。

arc 接受的参数依次为:

圆心位置 (100, 40)半径(20);起始的弧度(0,对应圆最右侧的点)结束的弧度(Math.PI * 2,刚好一圈)是否为逆时针绘制的布尔值,是可选值。默认为 false,即顺时针。

arc 方法执行完后,Canvas 心里就记住了这个路径。然后调用 fill 方法将路径填充,以及 stroke 方法沿着路径绘制线条。

beginPath 是表示我们后面要绘制新的路径的意思,可以防止描边时和上一次的路径相连。就好比把画笔提起来,准备画下一个图形。

当然我们画圆之前没有画过其他路径,所以这里不执行 beginPath 也是可以的。

绘制的结果如下:

image.png

绘制三角形

圆弧会画了,我们再来看看线条怎么画。以画三角形为例:

ctx.moveTo(20, 20);
ctx.lineTo(60, 20);
ctx.lineTo(40, 40);
ctx.fill();
ctx.closePath();
ctx.stroke();

首先是 moveTo 到坐标 (20, 20)

moveTo 其实就是将画笔抬起,放到对应的位置。它可以做到 beginPath 的效果:摆脱和之前的路径的关系。

然后是 lineTo 从当前位置沿着直线到达下一个点。接着又来一个 lineTo,此时我们画出了三角形的两条边。

此时如果你 fill(填充)其实是可以画出一个三角形的,因为填充逻辑是会将路径用直线封闭然后在填充的,第三条边存不存在效果相同。

但对 stroke(描边)就不同了,就导致只画出两条边。

于是我们调用 closePath 方法,将当前点和刚刚起笔的点(moveTo 时的点)进行直线相连。其实你可以再调用用一次 moveTo(20, 20) 来替代这个方法,这两个方法是等效的。

绘制的效果为:

image.png

结尾

本文介绍了 Canvas 的一些基础知识,并演示了绘制矩形、圆形、三角形比较基础的操作。

晚点我会再写其他介绍其他基础绘制操作的文章。


相关文章
|
Java 数据库连接 数据库
,从Flink 1.13版本开始,Flink Connector JDBC已经被移到了一个独立的仓库
,从Flink 1.13版本开始,Flink Connector JDBC已经被移到了一个独立的仓库
487 1
|
缓存 JavaScript 前端开发
vue-router学习二:动态路由(路由传递数据的一种方式),路由懒加载,嵌套路由,路由传递参数方式,导航守卫,keep-alive标签
这篇文章主要介绍了Vue Router的高级用法,包括动态路由、路由懒加载、嵌套路由、路由参数传递、导航守卫以及keep-alive的使用。
586 0
vue-router学习二:动态路由(路由传递数据的一种方式),路由懒加载,嵌套路由,路由传递参数方式,导航守卫,keep-alive标签
Vue3二维码(QRCode)
这是一个可高度定制的二维码生成组件,支持在线预览。提供了丰富的属性设置,包括扫描文本、二维码大小、颜色、背景色、边框、边框颜色、像素比例及纠错等级等。安装简单,通过 `pnpm` 引入插件,创建 `QRCode.vue` 组件即可使用。适用于多种应用场景,如生成不同样式的二维码、动态调整大小和内容等。
954 6
Vue3二维码(QRCode)
|
10月前
|
数据采集 监控 搜索推荐
用户画像构建:年度数据分析的用户视角
在数据驱动的时代,年度数据分析对企业战略规划和运营优化至关重要。本文从数据收集、预处理、分析、可视化到应用实践,全面探讨如何通过年度数据分析实现业务增长,助力企业精准决策。通过构建全面的数据源体系、清洗整合数据、洞察趋势、发现机会,并借助数据可视化工具,最终将数据转化为实际行动,持续优化企业运营。
|
资源调度 JavaScript Apache
Vue2使用echarts树图(tree)
这篇文章介绍了如何在Vue 3框架中集成echarts库来创建一个树状图(Tree Chart)组件,支持自定义数据和交互事件。
884 0
Vue2使用echarts树图(tree)
|
JavaScript 算法 API
Vue 3有哪些新特性
【8月更文挑战第16天】Vue 3有哪些新特性
896 1
|
存储 Kubernetes 监控
在K8S中,集群可以做哪些优化?
在K8S中,集群可以做哪些优化?
uniapp实战 —— 可滚动区域 scroll-view (自适配高度,下拉刷新)
uniapp实战 —— 可滚动区域 scroll-view (自适配高度,下拉刷新)
2735 0
|
存储 JavaScript 前端开发
uni-app 从vue3项目创建到Pinia管理数据全局使用 持久化存储数据 详细教程
uni-app 从vue3项目创建到Pinia管理数据全局使用 持久化存储数据 详细教程
|
域名解析 网络协议 程序员
网络原理(7)——以太网数据帧和DNS协议(数据链路层和应用层)
网络原理(7)——以太网数据帧和DNS协议(数据链路层和应用层)
668 0