前端canvas——贝塞尔曲线
曲线之美,不在于曲线本身,而在于用的人。
所以就有了这期贝塞尔曲线。
新规矩,先上个GIT。
效果图

开局一张图,代码全靠编。
代码
画骨
先想着怎么画一个心形吧,等你想好了,就知道怎么画了。
首先就还是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水平居中效果、图案居中缩放。
居中缩放,学一下了喂。
再见啦。
相关文章:
前端canvas——贝塞尔曲线
曲线之美,不在于曲线本身,而在于用的人。 所以就有了这期贝塞尔曲线。 新规矩,先上个GIT。 效果图 开局一张图,代码全靠编。 代码 画骨 先想着怎么画一个心形吧,等你想好了,就知道怎么画了。 首先就还…...
Elasticsearch模糊查询之Wildcard
{“wildcard” : { “LPR.keyword” : { “wildcard” : “${Keyword}”} }},你的示例中使用了 wildcard 查询,它适用于模糊搜索,允许使用通配符(* 和 ?)来匹配字段值。你使用了 keyword 子字段来确保精确匹配,这是一…...
【人工智能】穿越科技迷雾:解锁人工智能、机器学习与深度学习的奥秘之旅
文章目录 前言一、人工智能1. 人工智能概述a.人工智能、机器学习和深度学习b.人工智能发展必备三要素c.小案例 2.人工智能发展历程a.人工智能的起源b.发展历程 3.人工智能的主要分支 二、机器学习1.机器学习工作流程a.什么是机器学习b.机器学习工作流程c.特征工程 2.机器学习算…...
Nginx服务 rewrite、proxy_pass 用rewrite去除URL中的特定参数
Nginx 是一个高性能的开源反向代理服务器,可以用于处理跨域请求、负载均衡和缓存等功能。在本文中,我们将介绍如何使用 Nginx 配置文件来实现反向代理。 我们可以实现跨域请求的处理,同时保护用户的隐私和安全。此外,Nginx 还…...
RocketMQ事务消息机制原理
RocketMQ工作流程 在RocketMQ当中,当消息的生产者将消息生产完成之后,并不会直接将生产好的消息直接投递给消费者,而是先将消息投递个中间的服务,通过这个服务来协调RocketMQ中生产者与消费者之间的消费速度。 那么生产者是如何…...
【C++】选择结构- 嵌套if语句
嵌套if语句的语法格式: if(条件1) { if(条件1满足后判断是否满足此条件) {条件2满足后执行的操作} else {条件2不满足执行的操作} } 下面是一个实例 #include<iostream> using namespace std;int main4() {/*提示用户输入一个高考分数,根据分…...
scrapy解决管道阻塞问题采用threadpool库线程池+twisted同步语法异步编程
实现方法:process_item和download任务函数像下面编写即可,其他管道像往常一样写法 import time import threadpool import random from twisted.internet import deferclass VideoPipeline:def __init__(self):self.pool threadpool.ThreadPool(10) # …...
Axure RP:打造动态交互的大屏可视化设计利器
Axure大屏可视化是指使用Axure RP这款原型设计工具来创建具有视觉冲击力和数据展示功能的大屏幕界面。Axure以其强大的交互设计和丰富的组件库,成为了实现大屏可视化的重要工具之一。以下是对Axure大屏可视化的详细阐述: 一、Axure在大屏可视化中的优势 …...
“八股文”在实际工作中是助力、阻力还是空谈
目录 1.概述 1.1.对实际工作的助力 1.2.存在的问题 2.“八股文”对招聘过程的影响 2.1.“八股文”在筛选候选人时的作用 2.2.面试中的比重及其合理性 2.3.如何平衡“八股文”与实际编程能力的考察 3.“八股文”在日常工作中的实用价值 3.1.在团队协作环境中进行有效沟…...
项目开发:@ControllerAdvice注解的基本应用
目录 简介基本用法全局异常处理全局拦截器全局数据绑定 注解参数1.value(): String[]2.basePackages(): String[]3.basePackageClasses(): Class<?>[]4.assignableTypes(): Class<?>[]5.annotations(): Class<? extends Annotation>[] 三.注解组成总结 简…...
Jmeter三种方式获取数组中多个数据并将其当做下个接口参数入参【附带JSON提取器和CSV格式化】
目录 一、传统方式-JOSN提取器获取接口返回值 1、接口调用获取返回值 2、添加JSON提取器 3、调试程序查看结果 4、添加循环控制器 5、设置count计数器 6、添加请求 7、执行请求 二、CSV参数化 1、将结果写入后置处理程序 2、设置循环处理器 3、添加CSV文件 4、设置…...
C++入门基础:C++中的循环语句
循环语句是编程语言中用来重复执行一段代码直到满足特定条件的一种控制结构。它们对于处理需要重复任务的场景非常有用,比如遍历数组、累加数值、重复执行某项操作直到满足条件等。 但是在使用循环语句的时候需要注意下哈,有时候一不小心会构成死循环或者…...
VUE 基础(二)
1 v-show:根据表达值的真假,切换元素的显示和隐藏 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…...
VMware Cloud Foundation ESXi 主机
一、准备嵌套 ESXi 主机环境# 1)物理 ESXi 主机信息 本次准备用于部署 VCF 嵌套实验环境的物理宿主机的配置信息如下图所示。其实,部署 VCF 环境主要对内存的大小要求比较高,部署完整的管理域相关组件下来差不多就要占用 200 GB左右内存,而对 CPU 和存储的需求可以根据实…...
PyTorch深度学习快速入门(下)
PyTorch深度学习快速入门(下) 一、现有网络模型的使用及修改(一)背景知识(二)修改网络模型的三种方法 二、网络模型的保存与加载(一)保存网络模型的两种方法(二ÿ…...
轻松入门Linux—CentOS,直接拿捏 —/— <1>
一、什么是Linux Linux是一个开源的操作系统,目前是市面上占有率极高的服务器操作系统,目前其分支有很多。是一个基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的操作系统 Linux能运行主要的UNIX工具软件、应用程序和网络协议 Linux支持 32…...
pandas安装以及导入CSV
安装pandas pip install pandas速度慢可以切换国内镜像源 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas执行导入csv操作 import pandas as pd# 读取csv文件 data pd.read_csv(yourPath)输入data查看数据 导入成功!...
新能源车浪潮来袭,同时存在高压低压系统,如何准确进行高低压布线间距EMC分析?
摘要 随着车辆电气化水平的逐步提升,电气零部件布局和布线面临着前所未有的挑战,在不断的压缩电气零部件间间距后,EMC性能成为非常关键的性能指标。特别是对于新能源车型,同时存在高压和低压系统,高低压耦合若处理的不…...
QUIC 协议
详解 QUIC 协议:它为何比 TCP 更优越?...
【软件测试】--接口测试
1. 接口用例设计 接口测试的测试点 功能测试 单接口功能: 手工测试中的单个业务模块,一般对应一个接口 登陆业务 --> 登陆接口加入购物车业务 --> 加入购物车接口订单业务 --> 订单接口支付业务 --> 支付接口 借助工具、代码。绕开前端界面…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
java+webstock
maven依赖 <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version></dependency><dependency><groupId>org.apache.tomcat.websocket</groupId&…...
