前端canvas——贝塞尔曲线

曲线之美,不在于曲线本身,而在于用的人。

所以就有了这期贝塞尔曲线。

新规矩,先上个GIT。

效果图

 

d4200e37ebcf4c2aa045ea27b1a2a7ff.gif
 

开局一张图,代码全靠编。

 

代码

画骨

先想着怎么画一个心形吧,等你想好了,就知道怎么画了。

首先就还是JS创建Canvas,因为这样有代码提示。

        const canvas = document.createElement('canvas')canvas.width = canvas.height = 600document.body.append(canvas)

 

接着就是调用三阶的贝塞尔曲线,什么是三阶?

除了命名上不同,还有参考点个数不同——二阶的就一个参考点,三阶有很多个。

众所周知,心形其实是一个不规则的曲线,所以一个是不行的,至少不那么好看。

咱们就用三阶:

            ctx.beginPath()ctx.moveTo(300, 200)ctx.bezierCurveTo(40, 20, 0, 460, 300, 500)ctx.moveTo(300, 200)ctx.bezierCurveTo(560, 20, 600, 460, 300, 500)ctx.closePath()ctx.stroke()

 

里面的参考点坐标,自己想怎么来就怎么来。

前提是能看出来这是一个心形就OK了,看不出来也没关系,咱们最重要的在于怎么写动画。

 

如果你按照我的代码写,最终运行的效果中间是有一根线的,你可以stroke()两次,但是我“老奸巨猾”,选择了让画笔颜色消失。

当然啦,你也可以用fill(),这个是最好的。

我的宗旨:

道路千万条

这样,边框的颜色就没有了——因为边框没有了。

 

上色(可选)

画完这个,就得上色了。

上色很简单,你可以创建一个最简单的线性渐变色,然后fillStyle直接赋值即可。

你也可以追求花里胡哨,选择径向渐变,甚至是放射性渐变。

我这里选择径向渐变,代码就不给了,“心”的颜色取决于你喜欢什么色。

 

模糊(可选)

如果你跟我一样,Very Strong(跟我念,sizhuang)。

那你还可以上个模糊,模糊很简单,就四个参数,直接一股脑全巴拉巴拉写完就OK了:

            ctx.shadowColor = '#ccc' // 模糊颜色ctx.shadowOffsetX = 12 // 模糊坐标ctx.shadowOffsetY = 18ctx.shadowBlur = 58 // 模糊度数

对了,忘记告诉你了,模糊要在fill()和stroke()之前进行,要不然你铁定显示不出模糊效果。

模糊度数越高,你越看不清楚阴影。

至于取值,看你喜欢什么样的模糊效果,有投影的效果,有完全模糊的效果,都看你喜欢。

 

封装函数

封装函数都会吧?

-为什么要封装?

-为了后续调用。

对了,记得写个具名函数。

为了好理解,函数名我起init()——这都是学人的,美其名曰:企业级标准。

 

跳动的心

下面就是最困难的了——怎么让这个静止的心跳动起来了。

其实也很简单,那就是先把旧的图案去掉,换上新的。

道理就是这么个理,但是实现起来就很抽筋:

我们知道,心跳动是什么?

是一个过程,有来有回的。

你不能光来不回吧?

 

所以咱们得划定个范围,让“心”这个图案在这个范围内不停播放。

问:需要几个变量?

答:两个。

一个是步进量,一个是方向:

                if (scaleFactor >= 1.08 || scaleFactor <= 0.98) {scaleDirection *= (-1) // 改变缩放方向}

 

GIF图中是有个循环播放的效果的。

怎么循环呢?总不能用while吧?

好像又不是不行,就是你控制不了时间啊。

而且while很容易控制不住,死循环就炸鸡了。

既然提到时间了,那就用setInterval——定时器咯。

跟我拼写:s-e-t-I-n-t-e-r-v-a-l,setInterval。

 

思想工作完成,开始写函数,函数名写啥?

        function bounce() {let scaleFactor = 1let scaleDirection = 1setInterval(() => {ctx.clearRect(-300, -300, 600, 600)scaleFactor += 0.01 * scaleDirectionif (scaleFactor >= 1.08 || scaleFactor <= 0.98) {scaleDirection *= (-1)}// 应用变换并重新绘制心形ctx.save() // 保存当前画布状态ctx.scale(scaleFactor, scaleFactor)init() // 重新绘制心形ctx.restore() // 恢复画布到保存的状态}, 50)}

这个时间啊,就看你们自己调整了。

太快,不好看;太慢,又好像die了。

所以,你自己把握一下啦。

写完函数之后,记得调用函数,这样,咱们的动画就做好啦。

 

总结

又到了收工的时候,不知道你发现没发现,这个心居然不是原地跳动的。

这个怎么办捏?

当然是要付费学习的啦。

Tips:定位用一下啦。

 

最后给出所有代码:

    <script>const canvas = document.createElement('canvas')canvas.width = canvas.height = 600document.body.append(canvas)const ctx = canvas.getContext('2d')function init(){// 彩damn:先在这里改一下定位,然后下面的所有坐标位置都要修改ctx.beginPath()ctx.moveTo(300, 200)ctx.bezierCurveTo(40, 20, 0, 460, 300, 500)ctx.moveTo(300, 200)ctx.bezierCurveTo(560, 20, 600, 460, 300, 500)ctx.closePath()ctx.fill()}function bounce() {let scaleFactor = 1let scaleDirection = 1setInterval(() => {ctx.clearRect(0, 0, 600, 600)scaleFactor += 0.01 * scaleDirectionif (scaleFactor >= 1.08 || scaleFactor <= 0.98) {scaleDirection *= (-1)}// 应用变换并重新绘制心形ctx.save() // 保存当前画布状态ctx.scale(scaleFactor, scaleFactor)// ctx.translate(0, 0) // 彩damn:这个再次改变坐标轴的原点,配合上面。init() // 重新绘制心形ctx.restore() // 恢复画布到保存的状态}, 50)}bounce()</script>

 

-问:居中效果不会喔。

-答:是不是margin: auto不起作用啊。

-问:是喔,你怎么知道gie?

-答:Canvas是什么元素?不是块元素嘛,这个时候你要改变它的形状啊,用display嘛。

 

-问:你的效果这么piao亮gie?

-答:用了径向渐变、加了模糊效果,canvas水平居中效果、图案居中缩放。

 

居中缩放,学一下了喂。 

再见啦。

 

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

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

相关文章

iPhone 中阅读器模式是什么?怎么开启该模式?

什么是阅读器模式&#xff1f;这是一个浏览器功能&#xff0c;可以为用户提供简洁、干净的阅读界面。当你在 Safari 浏览器中启用阅读器模式时&#xff0c;网页上的广告、侧边栏和其他不相关的元素将被移除&#xff0c;仅保留主要的文字内容和相关图片。这使得用户可以专注于阅…

前端开发的十字路口,薪的出口会是AI吗?

前言 在数字化转型的浪潮中&#xff0c;前端开发一直扮演着至关重要的角色&#xff0c;它连接着用户与产品之间的桥梁。然而&#xff0c;随着技术的不断进步和社会经济环境的变化&#xff0c;前端开发领域也面临着前所未有的挑战和机遇。 前端开发的困境 前端开发领域的竞争…

Vue3多语言实现

1.首先安装i18n npm install vue-i18n 2.在项目下创建lang目录并创建en.ts,i18n1.ts,zh.ts en.ts export default {message: {home: home,appTitle:aa 3D Smart Measure}, Menus: {Measuer: Measure,},GlueMeasure: {Title: Camera 3D Glue Measure,}} zh.ts export …

android(安卓)最简单明了解释版本控制之MinSdkVersion、CompileSdkVersion、TargetSdkVersion

1、先明白几个概念 &#xff08;1&#xff09;平台版本&#xff08;Android SDK版本号&#xff09; 平台版本也就是我们平时说的安卓8、安卓9、安卓10 &#xff08;2&#xff09;API级别&#xff08;API Level&#xff09; Android 平台提供的框架 API 被称作“API 级别” …

什么是CAN的BUS-OFF,如何恢复BUS-OFF?

CAN作为一款强大的工业总线&#xff0c;其高性能和高可靠性让其应用特别广泛。一个小知识&#xff1a;汽车里面各个模块之间的通讯就是使用CAN来实现的哦。 既然是总线&#xff0c;那当然会有多个设备挂载在CAN上&#xff0c;当一个设备在发送数据的时候&#xff0c;其他设备也…

基于STC8H4K64TL单片机的RTC(即实时时钟)功能调试

基于STC8H4K64TL单片机的RTC(即实时时钟)功能调试 STC8H4K64TL单片机介绍STC8H4K64TL单片机管脚图(48个引脚)STC8H4K64TL单片机串口仿真与串口通信STC8H4K64TL单片机管脚图(32个引脚)STC8H4K64TL单片机管脚图(20个引脚)STC8H系列单片机管脚说明STC8H系列单片机I/O口STC…

大模型不会比大小和单词字母计数?日期计算也是一片混乱

9.9和9.11哪个大&#xff1f;13.8%和13.11%谁大谁小&#xff1f;这两个比大小的问题&#xff0c;前段时间难倒众多大模型&#xff0c;在网上掀起热议。 除此之外&#xff0c;向大模型提问“草莓&#xff08;strawberry&#xff09;这个单词有几个r时”&#xff0c;多家主流大模…

三目操作符

双目操作符有、-、*、/、% 单目操作符有--、、、- 三目操作符有表达式1&#xff1f;表达式2&#xff1a;表达式3 如果表达式1为真则表达式2计算否则表达式3计算&#xff0c;计算结果为整个表达式的结果 #include<stdio.h> int main() {int a 0;int b 0;scanf(&quo…

Doris-计算特性

1 全新优化器 1.1 如何开启1.2 统计信息 1.2.1 使用ANALYZE语句手动收集1.2.1 自动收集1.2.3 作业管理1.3 会话变量及配置项调优参数2 Join相关 2.1 支持的Join算子2.2 支持的shuffle方式 2.2.1 Broadcast Join2.2.2 Shuffle Join2.2.3 Bucket Shuffle Join 2.2.3.1 原理2.2.3.…

PHP反序列化漏洞从入门到深入8k图文介绍,以及phar伪协议的利用

文章参考&#xff1a;w肝了两天&#xff01;PHP反序列化漏洞从入门到深入8k图文介绍&#xff0c;以及phar伪协议的利用 前言 本文内容主要分为三个部分&#xff1a;原理详解、漏洞练习和防御方法。这是一篇针对PHP反序列化入门者的手把手教学文章&#xff0c;特别适合刚接触PH…

Windows搭建我的世界MC服务器 【Minecraft外网联机教程】

目录 ⛳️推荐 1. 搭建我的世界服务器 1.1 服务器安装java环境 1.2 配置服务端 1.3 创建我的世界服务器 2. 局域网联机测试 3. 安装cpolar内网穿透 4. 公网联机Minecraft 5. 配置固定远程联机端口地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通…

新手转行AI运营岗位,轻松实现月入15K+

近年来人工智能大爆发&#xff0c;各种AI产品层出不穷&#xff0c;市场也出现了一批高薪AI运营类岗位 不需要技术背景、门槛低&#xff0c;即便是新手&#xff0c;也有机会拿下offer。如果你计划今年跳槽或转行运营&#xff0c;这5个岗位不妨试试&#xff08;结尾附国内AI公司清…

科普文:万字梳理高性能 Kafka快的8个原因

概叙 科普文&#xff1a;万字详解Kafka基本原理和应用-CSDN博客 科普文&#xff1a;万字梳理31个Kafka问题-CSDN博客 我们都知道 Kafka 是基于磁盘进行存储的&#xff0c;但 Kafka 官方又称其具有高性能、高吞吐、低延时的特点&#xff0c;其吞吐量动辄几十上百万。 在座的…

【深度学习】kaggle使用

https://blog.csdn.net/2301_78630677/article/details/133834096 https://blog.csdn.net/xiaojia1001/article/details/139467176 https://www.kaggle.com/ 使用要挂代理&#xff0c;要不然可能无法注册 绑定手机号之后才能使用GPU 每周30h免费GPU使用时长 上传数据集 Ad…

安科瑞ACTB系列电流互感器过电压保护器

产品概述&#xff1a; 安科瑞ACTB系列电流互感器过电压保护器是一种重要的电力保护设备&#xff0c;‌主要用于防止电流互感器在运行中因二次绕组开路或一次绕组流过异常电流而在二次侧产生的高压过电压。‌这种保护器能有效防止因电流互感器二次侧异常高压引起的事故&#xf…

手撕数据结构---栈和队列的概念以及实现

栈的概念&#xff1a; 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶&#xff0c;另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈…

opencascade AIS_RubberBand AIS_RotationMode源码学习

//!相机旋转类型 Camera rotation mode. enum AIS_RotationMode { AIS_RotationMode_BndBoxActive, //!< default OCCT rotation AIS_RotationMode_PickLast, //!< rotate around last picked point AIS_RotationMode_PickCenter, //!< rotate around point at the ce…

python之代码简化式(列表、字典生成式,递归函数,迭代器(iter)和生成器(yield)、匿名函数(lambda)的使用)(12)

文章目录 前言1、列表、字典生成式2、递归函数2.1 python中代码的递归深度&#xff08;扩展&#xff09; 3、拓展&#xff1a;迭代器和生成器3.1 迭代器&#xff08;iter&#xff09;3.2 生成器&#xff08;yield&#xff09; 4、匿名函数&#xff08;lambda&#xff09;4.1 ma…

宠物猫用空气净化器真的有用吗?值得买的猫用空气净化器牌子排名

作为一名6年资深铲屎官&#xff0c;每天铲猫砂盆的工作无疑是一项挑战。家中不仅弥漫着难以忍受的气味&#xff0c;而且家里的小孩和老人偶尔会因为过敏性鼻炎或结膜炎等问题感到不适。换毛季节尤其头疼&#xff0c;浮毛无处不在&#xff1a;沙发、外套、坐垫&#xff0c;甚至连…

Spring Boot 3 + Resilience4j 简单入门 + Redis Cache 整合

1. 项目结构 2. Maven依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.2</version><relativePath/> <!-- lookup parent from repository --&…