Canvas:掌握贝塞尔曲线与封装路径

想象一下,用几行代码就能创造出如此逼真的图像和动画,仿佛将艺术与科技完美融合,前端开发的Canvas技术正是这个数字化时代中最具魔力的一环,它不仅仅是网页的一部分,更是一个无限创意的画布,一个让你的想象力自由驰骋的平台。

目录

初识canvas

路径绘制

贝塞尔曲线

封装路径(Path2D)

初识canvas

身为一个WEB开发人员,肯定都是想着能够开发出酷炫和激动人心的应用程序来,想开发出很多动画特效,例如黑客帝国的数字,彩色炫酷的例子动效。也可以实现各种图画面板,如实现类似于photoshop的web在线图像编辑。各种酷炫的表单等等,接下来我们通过一段简单的代码来了解如何实现一个画布:

通过canvas标签创建一个画布,通过getContext函数设置2d画笔,然后通过fillRect函数创建一个画布的位置与大小,代码如下:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制图形,矩形 fillRect(x, y, width, height) 参数位置x,位置y,宽度,高度ctx.fillRect(100, 200, 300, 300);</script>
</body>

执行代码在浏览器打开的界面得到的结果如下所示,可以看到我们在浏览器得到一个黑色的区域,在这我们可以看到,我们在canvas设置的宽高是画布的初始宽高,这里可以传递实际宽高,相当于一张图片有一个初始宽高,可以对这张图片进行放大缩小操作:

当然我们也可以对 fillRect 函数继续拆开来书写,代码如下达到的效果是一样的:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制图形ctx.rect(100, 200, 300, 300); // 绘制矩形ctx.fillStyle = "red"; // 填充颜色ctx.fill(); // 填充</script>
</body>

如果想要清除画布中的样式的话,可以采用clearRect函数的方法进行,这里做一个简单的代码示例:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制图形ctx.fillRect(100, 100, 200, 200);let height = 0let t1 = setInterval(() => {height++ctx.clearRect(0, 0, canvas.clientWidth, height);if (height > canvas.clientHeight) {clearInterval(t1)}}, 10)</script>
</body>

得到的效果如下所示:

浏览器兼容性:至今已经2024年了,我相信大家的电脑浏览器已经普遍是最新版本的浏览器,除非长期使用比较古老的浏览器或者说很久都没有更新过浏览器的人来说,可能存在不兼容canvas的情况。因为只有canvas才有getContext函数,所以这里我们也可以对canvas做一个判断:

let canvas = document.getElementById("canvas");
// 判断是否有getContext
if (canvas.getContext) {console.log("当前浏览器不支持canvas,请下载最新浏览器");
}

当然这里我们也可以直接写在canvas标签中,因为如果canvas不能被识别的情况下会将canvas作为一个普通的标签进行执行,所以会直接呈现canvas标签内部的内容:

<canvas id="canvas" width="600" height="400">当前浏览器不支持canvas,请下载最新浏览器<a href="www.baidu.com">立即下载</a>
</canvas>

当然canvas还有许多API函数可以使用,如果忘记的话,可以查阅 MDN ,进行查看:

路径绘制

在我们设置画布的时候,画布内部是有规定的坐标的,我们可以通过拿到特定的坐标可以绘制一个特定的曲线,所以我们需要告诉canvas的画笔坐标的落点是在哪里?我们要在什么样的位置画什么样的图案。

在我们开始画图之前,我们需要了解一下画布栅格(canvasgrid)以及坐标空间,如下图所示,canvas元素默认被网格所覆盖。通常来说网格中的一个单元相当于canvas元素中的一像素。

栅格的起点为左上角(坐标为(0,0)),所有元素的位置都相对于原点定位,所以图中蓝色方形左上角的坐标为距离左边(X轴)×像素,距离上边(Y轴)y像素(坐标为(x,y)):

绘制矩形:可以通过strokeRect函数进行,这里通过如下代码示例进行演示:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制图形,路径绘制矩形 strokeRect(x1, y1, 矩形宽度, 矩形高度)ctx.strokeRect(100, 100, 200, 100);</script>
</body>

在页面得到的结果如下所示:

绘制圆形:当然如果想绘制圆形的话可以采用如下的代码方式,使用arc函数绘制圆弧传递6个参数即可:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制圆弧 圆形x坐标 y坐标 半径 起始角度 结束角度 顺时针/逆时针(默认顺时针)console.log(Math.PI / 2)ctx.arc(300, 200, 50, 0, Math.PI / 2, true) ctx.stroke()</script>
</body>

得到的画面如下所示:

如果想绘制一个简单的笑脸的话,可以采用如下的方式进行,因为canvas是连续的,也就是画笔是不会自动抬起而是一直画下去,这里需要我们手动的指定画笔的抬起进行书写样式,具体代码如下所示:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制圆脸ctx.beginPath(); // 开始绘制ctx.arc(75, 75, 50, 0, Math.PI * 2);ctx.stroke()ctx.closePath(); // 闭合路径ctx.beginPath();// 绘制嘴巴ctx.arc(75, 75, 35, 0, Math.PI);ctx.stroke()ctx.closePath(); ctx.beginPath();// 绘制左眼ctx.arc(60, 65, 5, 0, Math.PI * 2);ctx.stroke()ctx.closePath(); ctx.beginPath();// 绘制右眼ctx.arc(90, 65, 5, 0, Math.PI * 2);ctx.closePath(); ctx.stroke()</script>
</body>

绘制线段:如果想绘制一条从当前位置到指定x以及y位置的直线,可以采用的方式是lineTo方法:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制线段ctx.moveTo(300, 200); // 起点ctx.lineTo(350, 250); // 终点 起点ctx.lineTo(350, 200); // 终点 起点ctx.lineTo(300, 200); // 终点ctx.stroke();</script>
</body>

最终呈现的效果如下所示:

绘制圆弧:当然这里我们也可以通过arcTo方法进行绘制圆弧,给出如下代码示例:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");// 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 绘制线段ctx.moveTo(300, 200); // 第一个点ctx.arcTo(300, 250, 250, 250, 25); // 第二个和第三个点以及圆弧半径 ctx.stroke();</script>
</body>

其大致的意思如下,三个点组成的线段相切得到的圆弧片段就是我们想要的:

贝塞尔曲线

贝塞尔曲线是一种数学曲线,通常用于在计算机图形学和计算机辅助设计(CAD)中绘制平滑曲线,它由法国工程师皮埃尔·贝塞尔(Pierre Bézier)在20世纪60年代提出并广泛应用于汽车工业的设计中,贝塞尔曲线通过控制点(称为贝塞尔控制点)来定义曲线的形状,其形式简单且易于计算,因此在计算机图形学中得到了广泛应用,如绘制曲线、字体设计、动画制作等领域,在canvas中贝塞尔曲线也是被广泛应用,本文就其做一个简单的概述供大家学习了解:

二次贝塞尔曲线:由三个控制点定义,形状相对简单。

1)由三个控制点定义:起始点P0,控制点P1,终点P2。

2)曲线不经过P1点,但P1点影响曲线的形状。

3)用途:二次贝塞尔曲线通常用于较简单的曲线绘制和动画路径。

这边我们可以做一个气泡聊天框进行一个简单的练习,详细的代码如下所示:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");      // 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 初始起点ctx.moveTo(200, 300)// 绘制二次贝塞尔曲线/*  二次贝塞尔曲线 ctx.quadraticCurveTo(cx, cy, x, y) 中,四个参数的含义如下:cx: 控制点的 x 坐标。这个点影响曲线的弯曲方向和弧度。cy: 控制点的 y 坐标。与 cx 一起决定了曲线的形状。x: 曲线的终点 x 坐标。这是曲线将要到达的目标点。y: 曲线的终点 y 坐标。与 x 一起决定了曲线的最终位置。*/ctx.quadraticCurveTo(150, 300, 150, 200); ctx.quadraticCurveTo(150, 100, 300, 100); ctx.quadraticCurveTo(450, 100, 450, 200); ctx.quadraticCurveTo(450, 300, 250, 300); ctx.quadraticCurveTo(250, 350, 150, 350); ctx.quadraticCurveTo(200, 350, 200, 300); ctx.stroke()</script>
</body>

程序的效果如下所示,效果还不错:

三次贝塞尔曲线:由四个控制点定义,更能描述复杂的曲线。

1)由四个控制点定义:起始点P0,控制点P1,控制点P2,终点P3。

2)曲线经过起始点P0和终点P3,但不一定经过控制点P1和P2。

3)用途:三次贝塞尔曲线比二次更灵活,适用于更复杂的曲线绘制,如字体设计、CAD绘图、动画路径等。

这里我们可以借助三次贝塞尔曲线做一个简单的爱心:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");      // 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");// 初始起点ctx.moveTo(300, 200)/* 第一个控制点和第二个控制点是曲线弯曲方向的关键点第三个控制点 终点是曲线最终到达的目标点*/ctx.bezierCurveTo(350, 150, 400, 200, 300, 300); ctx.bezierCurveTo(200, 200, 250, 150, 300, 200); ctx.stroke()</script>
</body>

程序的效果如下所示,效果还不错:

二次和三次贝塞尔曲线在计算机图形学中广泛用于平滑曲线的生成和路径控制,它们被用来设计字体、绘制图形、创建动画路径、制作CAD图形等,其简单的数学形式和良好的平滑性使它们成为计算机图形学中不可或缺的工具之一。

封装路径(Path2D)

在canvas中,Path2D是一个对象用来存储和重用路径描述信息,从而方便地绘制相同或类似的路径多次,尤其适合于需要频繁使用复杂路径的场景,这里我们做一个简单的概述:

通过如下代码把路径存在2d对象中,下次想要操作这个路径,就直接把2d对象传给fill或者描边方法就行了,如下给出代码示例:

<body><canvas id="canvas" width="600" height="400"></canvas><script>let canvas = document.getElementById("canvas");      // 获取2维画笔,上下文对象let ctx = canvas.getContext("2d");let heartPath = new Path2D();// 初始起点heartPath.moveTo(300, 200)heartPath.bezierCurveTo(350, 150, 400, 200, 300, 300); heartPath.bezierCurveTo(200, 200, 250, 150, 300, 200); ctx.stroke(heartPath)let chatPath = new Path2D();chatPath.moveTo(200, 300)chatPath.quadraticCurveTo(150, 300, 150, 200); chatPath.quadraticCurveTo(150, 100, 300, 100); chatPath.quadraticCurveTo(450, 100, 450, 200); chatPath.quadraticCurveTo(450, 300, 250, 300); chatPath.quadraticCurveTo(250, 350, 150, 350); chatPath.quadraticCurveTo(200, 350, 200, 300); ctx.stroke(chatPath)ctx.fill(heartPath)</script>
</body>

页面呈现的效果如下所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/864728.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件夹加密软件推荐,这款软件满足各种加密需求

文件夹加密是保护电脑数据安全的重要方式&#xff0c;而在加密文件夹时&#xff0c;我们需要选择专业的文件夹加密软件。下面小编就为大家推荐一款优秀的文件夹加密软件&#xff0c;满足你的各种文件夹加密需求。 文件夹加密超级大师 由于文件夹储存的数据不同&#xff0c;比如…

MCU 是什么?一文了解MCU 产业

MCU&#xff08;Microcontroller Unit&#xff09;&#xff0c;中文名为“微控制器单元”、“单片微型计算机”。MCU 将中央处理器&#xff08;CPU&#xff09;、内存&#xff08;RAM&#xff09;、输入 / 输出界面&#xff08;I/O&#xff09;等等一大堆东西&#xff0c;全部整…

数据结构——带环链表、循环队列问题

1.带环链表问题 1.1给定一个链表判断其是否带环 解决思路&#xff1a;利用快慢指针法&#xff0c;快指针一次走两步慢指针一次走一步&#xff0c;从链表起始位置遍历链表&#xff0c;如果链表带环&#xff0c;则快慢指针一定会在环中相遇&#xff0c;否则快指针先到达链表末尾…

Kafka-服务端-副本同步-源码流程

杂 在0.9.0.0之前&#xff0c;Kafka提供了replica lag.max.messages 来控制follower副本最多落后leader副本的消息数量&#xff0c;follower 相对于leader 落后当超过这个数量的时候就判定该follower是失效的&#xff0c;就会踢出ISR&#xff0c;这里的指的是具体的LEO值。 对…

软考高级之系统分析师及系统架构设计师备考过程记录

0x00 前言 考了两次系分&#xff0c;一次架构&#xff0c;今年系分终于上岸。 在此记录备考过程和一些体会 先说我自己的情况&#xff0c;我本硕都是计算机科班出身&#xff0c;本科的时候搞Java后端开发&#xff0c;硕士搞python和深度学习&#xff0c;但工作之后就基本没碰过…

洞鉴-产品部署及其功能

网络策略&#xff1a;安装&#xff1a; 资源准备 ⼀、系统安装包 https://chaitin-release.oss-cnbeijing.aliyuncs.com/release%2Ff%2F66600aac66bcea13c086319c?Expires1719310707 &OSSAccessKeyIdLTAI5tBpSz7iLYLH51NrVx22&SignaturesOpuVYuKpm9ZBoEzfwiRlJ fLrhQ…

STM32 HAL库读取ID

在stm32f1xx_hal.c文件中由读取ID号的子函数&#xff0c;不同单片机的UID_BASE不同&#xff0c;本单片机用的是STM32F103CBT6,跳转之后可以看到地址为&#xff1a;0x1FFFF7E8 在程序中只需定义一个数组调用读取ID的函数即可 uint32_t UID[3]; while(1) { UID[0] HAL_GetUIDw0…

C盘清理和管理

本篇是C盘一些常用的管理方法&#xff0c;以及定期清理C盘的方法&#xff0c;大部分情况下都能避免C盘爆红。 C盘清理和管理 C盘存储管理查看存储情况清理存储存储感知清理临时文件清理不需要的 迁移存储 磁盘清理桌面存储管理应用存储管理浏览器微信 工具清理 C盘存储管理 查…

VUE3+ AntV Select 选择器:mode=“multiple“和mode=“tags“的区别是什么

文章目录 VUE3 AntV Select 选择器&#xff1a;mode"multiple"和mode"tags"的区别是什么一、解释二、对比演示 VUE3 AntV Select 选择器&#xff1a;mode"multiple"和mode"tags"的区别是什么 一、解释 “mode” 是一个参数&#xff…

SpringSecurity中文文档(Servlet Persisting Authentication)

Persisting Authentication 用户第一次请求受保护的资源时&#xff0c;系统会提示他们输入凭据。提示凭据的最常见方法之一是将用户重定向到登录页。对于请求受保护资源的未经身份验证的用户&#xff0c;总结的 HTTP 交换可能如下所示: Example 1. Unauthenticated User Requ…

VBA字典与数组第十六讲:行、列数不相同的数组间运算规律

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…

【SpringCloud】Config源码解析

config是一个微服务配置组件&#xff0c;为微服务提供集中化的配置管理服务。config包含服务端和客户端&#xff0c;客户端在启动服务时从服务端拉取配置信息&#xff0c;服务端响应客户端的请求提供具体的配置。本章分析config组件配置信息的拉取过程 1、config服务端 服务端…

一键AI抠图太方便啦!不会ps也能成为修图大师

引言 在数字生活中&#xff0c;抠图技能已成为一项日常且必不可少的技能。无论是需要更换证件照的背景色&#xff0c;还是想要将图像中的主体精确分离。 但并非所有人都精通Photoshop&#xff0c;而且对于简单的任务来说&#xff0c;使用Photoshop可能显得过于复杂。因此&…

1077 韩信点兵

这是一个中国剩余定理的问题。中国剩余定理是数论中的一个定理&#xff0c;它给出了一组同余方程的解的存在性和唯一性。在这个问题中&#xff0c;我们需要找到一个数&#xff0c;使得它对给定的每个质数取余的结果等于给定的余数。 以下是一个使用C实现的解决方案&#xff1a…

Spark2.0

目录 10.3 Spark运行架构 10.3.1 基本概念 10.3.2 架构设计 ​编辑 10.3.3 Spark运行基本流程 Spark运行架构特点 10.3 Spark运行架构 10.3.1 基本概念 RDD &#xff1a;是 Resillient Distributed Dataset &#xff08;弹性分布式数据集&#xff09;的简称&#xff0c;是分…

【Llama 2的使用方法】

Llama 2是Meta AI&#xff08;Facebook的母公司Meta的AI部门&#xff09;开发并开源的大型语言模型系列之一。Llama 2是在其前身Llama模型的基础上进行改进和扩展的&#xff0c;旨在提供更强大的自然语言处理能力和更广泛的应用场景。 以下是Llama 2的一些关键特性和更新点&am…

git主机仓库地址迁移后 git提交代码报错

找到本地电脑的文件known_hosts 2.在代码中git pull 此时终端会有提示 输入ye enter提交便成功了

springboot个人证书管理系统-计算机毕业设计源码16679

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了个人证书管理系统的开发全过程。通过分析个人证书管理系统管理的不足&#xff0c;创建了一个计算机管理个人证书管理系统的方案。文章介绍了个人证书管理系统的系…

豪掷5400亿,SK海力士加码部署AI赛道

KlipC报道&#xff1a;最新数据显示&#xff0c;韩国6月半导体出口额达到134亿美元&#xff08;约合人民币973亿元&#xff09;&#xff0c;同比增长50.9%。 KlipC分析师表示&#xff0c;这一数据超出市场预期&#xff0c;对于全球半导体产业链来说&#xff0c;是一则利好的消…

2024年【四川省安全员A证】试题及解析及四川省安全员A证模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 四川省安全员A证试题及解析根据新四川省安全员A证考试大纲要求&#xff0c;安全生产模拟考试一点通将四川省安全员A证模拟考试试题进行汇编&#xff0c;组成一套四川省安全员A证全真模拟考试试题&#xff0c;学员可通…