爱心动画代码HTML5

这段代码是一个HTML5 Canvas动画,它通过JavaScript创建了一个动态的爱心效果。页面初始化时,首先定义了一些基本设置,如粒子数量、持续时间、速度等。然后,定义了Point和Particle类,用于处理粒子的位置和运动。接着,使用ParticlePool管理粒子池,实现粒子的循环利用。

核心动画逻辑在`render`函数中,这个函数会在每一帧调用`requestAnimationFrame`来更新和渲染粒子。动画效果通过在Canvas上绘制粒子来实现,粒子从爱心形状的路径上发射出来,随着时间逐渐消失,形成了一个连续的动态效果。

此外,还有一个`pointOnHeart`函数用于生成爱心形状的路径点,以及一个辅助函数用于创建粒子图像。整个动画在全屏黑色背景上运行。

整体来看,这段代码展示了如何使用HTML5 Canvas和JavaScript来创建复杂的动画效果,适合用于网页装饰或特殊场合的视觉效果展示。

<!DOCTYPE html>
<html><head><title></title>
</head>
<style>* {padding: 0;margin: 0;}html,body {height: 100%;padding: 0;margin: 0;background: #000;}canvas {position: absolute;width: 100%;height: 100%;}.aa {position: fixed;/* 固定位置 */left: 50%;/* 向左移动自身宽度的50% */transform: translateX(-50%);/* 向左移动自身宽度的50%,实现水平居中 */top: 45%;color: #ccc;/* 文字颜色设置为灰色 */font-family: Arial, sans-serif;/* 设置字体 */font-size: 30px;/* 设置字体大小 */}
</style><body><canvas id="pinkboard"></canvas><div class="aa">美羊羊</div> <!-- 名字 --><script>/** 设置动画参数*/var settings = {particles: {length: 500, // 粒子的最大数量duration: 2, // 粒子存在的时间(秒)velocity: 100, // 粒子的速度(像素/秒)effect: -0.75, // 控制粒子运动效果的参数size: 30 // 粒子的大小(像素)},};/** RequestAnimationFrame polyfill by Erik M?ller*/(function () { var b = 0; var c = ["ms", "moz", "webkit", "o"]; for (var a = 0; a < c.length && !window.requestAnimationFrame; ++a) { window.requestAnimationFrame = window[c[a] + "RequestAnimationFrame"]; window.cancelAnimationFrame = window[c[a] + "CancelAnimationFrame"] || window[c[a] + "CancelRequestAnimationFrame"] } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (h, e) { var d = new Date().getTime(); var f = Math.max(0, 16 - (d - b)); var g = window.setTimeout(function () { h(d + f) }, f); b = d + f; return g } } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (d) { clearTimeout(d) } } }());/** 点(Point)类,用于处理二维空间中的点*/var Point = (function () {function Point(x, y) {this.x = (typeof x !== 'undefined') ? x : 0;this.y = (typeof y !== 'undefined') ? y : 0;}Point.prototype.clone = function () {return new Point(this.x, this.y);};Point.prototype.length = function (length) {if (typeof length == 'undefined')return Math.sqrt(this.x * this.x + this.y * this.y);this.normalize();this.x *= length;this.y *= length;return this;};Point.prototype.normalize = function () {var length = this.length();this.x /= length;this.y /= length;return this;};return Point;})();/** 粒子(Particle)类,用于创建和管理动画中的粒子*/var Particle = (function () {function Particle() {this.position = new Point();this.velocity = new Point();this.acceleration = new Point();this.age = 0;}Particle.prototype.initialize = function (x, y, dx, dy) {this.position.x = x;this.position.y = y;this.velocity.x = dx;this.velocity.y = dy;this.acceleration.x = dx * settings.particles.effect;this.acceleration.y = dy * settings.particles.effect;this.age = 0;};Particle.prototype.update = function (deltaTime) {this.position.x += this.velocity.x * deltaTime;this.position.y += this.velocity.y * deltaTime;this.velocity.x += this.acceleration.x * deltaTime;this.velocity.y += this.acceleration.y * deltaTime;this.age += deltaTime;};Particle.prototype.draw = function (context, image) {function ease(t) {return (--t) * t * t + 1;}var size = image.width * ease(this.age / settings.particles.duration);context.globalAlpha = 1 - this.age / settings.particles.duration;context.drawImage(image, this.position.x - size / 2, this.position.y - size / 2, size, size);};return Particle;})();/** 粒子池(ParticlePool)类,用于高效管理大量粒子*/var ParticlePool = (function () {var particles,firstActive = 0,firstFree = 0,duration = settings.particles.duration;function ParticlePool(length) {// create and populate particle poolparticles = new Array(length);for (var i = 0; i < particles.length; i++)particles[i] = new Particle();}ParticlePool.prototype.add = function (x, y, dx, dy) {particles[firstFree].initialize(x, y, dx, dy);// handle circular queuefirstFree++;if (firstFree == particles.length) firstFree = 0;if (firstActive == firstFree) firstActive++;if (firstActive == particles.length) firstActive = 0;};ParticlePool.prototype.update = function (deltaTime) {var i;// update active particlesif (firstActive < firstFree) {for (i = firstActive; i < firstFree; i++)particles[i].update(deltaTime);}if (firstFree < firstActive) {for (i = firstActive; i < particles.length; i++)particles[i].update(deltaTime);for (i = 0; i < firstFree; i++)particles[i].update(deltaTime);}// remove inactive particleswhile (particles[firstActive].age >= duration && firstActive != firstFree) {firstActive++;if (firstActive == particles.length) firstActive = 0;}};ParticlePool.prototype.draw = function (context, image) {// draw active particlesif (firstActive < firstFree) {for (i = firstActive; i < firstFree; i++)particles[i].draw(context, image);}if (firstFree < firstActive) {for (i = firstActive; i < particles.length; i++)particles[i].draw(context, image);for (i = 0; i < firstFree; i++)particles[i].draw(context, image);}};return ParticlePool;})();/** 动画的主要逻辑*/(function (canvas) {var context = canvas.getContext('2d'),particles = new ParticlePool(settings.particles.length),particleRate = settings.particles.length / settings.particles.duration, // particles/sectime;// 根据给定的参数t,计算爱心形状上的点function pointOnHeart(t) {return new Point(160 * Math.pow(Math.sin(t), 3),130 * Math.cos(t) - 50 * Math.cos(2 * t) - 20 * Math.cos(3 * t) - 10 * Math.cos(4 * t) + 25);}// 创建粒子图像,用于在动画中显示var image = (function () {var canvas = document.createElement('canvas'),context = canvas.getContext('2d');canvas.width = settings.particles.size;canvas.height = settings.particles.size;// helper function to create the pathfunction to(t) {var point = pointOnHeart(t);point.x = settings.particles.size / 2 + point.x * settings.particles.size / 350;point.y = settings.particles.size / 2 - point.y * settings.particles.size / 350;return point;}// create the pathcontext.beginPath();var t = -Math.PI;var point = to(t);context.moveTo(point.x, point.y);while (t < Math.PI) {t += 0.01; // baby steps!point = to(t);context.lineTo(point.x, point.y);}context.closePath();// create the fillcontext.fillStyle = '#ea80b0';context.fill();// create the imagevar image = new Image();image.src = canvas.toDataURL();return image;})();// 渲染函数,用于每一帧的动画绘制function render() {// next animation framerequestAnimationFrame(render);// update timevar newTime = new Date().getTime() / 1000,deltaTime = newTime - (time || newTime);time = newTime;// clear canvascontext.clearRect(0, 0, canvas.width, canvas.height);// create new particlesvar amount = particleRate * deltaTime;for (var i = 0; i < amount; i++) {var pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random());var dir = pos.clone().length(settings.particles.velocity);particles.add(canvas.width / 2 + pos.x, canvas.height / 2 - pos.y, dir.x, -dir.y);}// update and draw particlesparticles.update(deltaTime);particles.draw(context, image);}// 处理Canvas大小变化的函数function onResize() {canvas.width = canvas.clientWidth;canvas.height = canvas.clientHeight;}window.onresize = onResize;// 延迟启动渲染,确保页面元素加载完毕setTimeout(function () {onResize();render();}, 10);})(document.getElementById('pinkboard'));</script>
</body></html>

效果图: 

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

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

相关文章

C语言数据类型和变量

数据类型介绍 数据类型介绍 C语言提供了丰富的数据类型来描述生活中的各种数据。 使用整型类型来描述整数&#xff0c;使用字符类型来描述字符&#xff0c;使用浮点型类型来描述小数。 所谓“类型”&#xff0c;就是相似的数据所拥有的共同特征&#xff0c;编译器只有知道了数…

软件测试经典面试题,助你面试加分

Hi&#xff0c;大家好&#xff0c;进入金九银十&#xff0c;很多小伙伴有被动跳槽的打算&#xff0c;所以更新一些经典的软件测试面试题&#xff0c;希望能帮到大家&#xff01; 时间紧迫的情况下&#xff0c;如何做好测试工作&#xff1f; 对需求要明确&#xff0c;对需求的优…

iPhone如何全选删除照片:一步到位的清理指南

随着时间的推移&#xff0c;iPhone中的照片会迅速累积&#xff0c;最终可能占据大量的存储空间。无论是为了释放空间&#xff0c;还是整理照片库&#xff0c;iPhone如何全选删除照片成为许多用户的需求。然而&#xff0c;iPhone原生的“照片”应用并没有直接提供“全选删除”功…

汽车租赁管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图详细视频演示技术栈系统测试为什么选择我官方认证玩家&#xff0c;服务很多代码文档&#xff0c;百分百好评&#xff0c;战绩可查&#xff01;&#xff01;入职于互联网大厂&#xff0c;可以交流&#xff0c;共同进步。有保障的售后 代码参考数据库参…

SAIA触摸屏维修PCD7.D457VNCG03 SAIA-burgess

瑞士SAIA触摸屏维修SAIA-burgess思博控制器维修PCD7全系列。 触摸屏维修常见故障&#xff1a;黑屏、指示灯无任何显示&#xff0c;触摸屏上电无反应&#xff0c; 上电蓝屏、白屏&#xff0c;通电几分钟后屏幕变为蓝屏&#xff0c;主板故障&#xff0c;通讯时有时无&#xff0c…

LiveQing视频点播流媒体RTMP推流服务用户手册-概览:CPU使用、内存使用、在线人数、流量统计、带宽使用(Mbps)、存储使用、实时存储(MB/s)

LiveQing视频点播流媒体RTMP推流服务用户手册-概览:CPU使用、内存使用、在线人数、流量统计、带宽使用&#xff08;Mbps&#xff09;、存储使用、实时存储&#xff08;MB/s&#xff09; 1、概览1.1、CPU使用1.2、内存使用1.3、在线人数1.4、流量统计1.5、带宽使用(Mbps)1.6、存…

2024年系统集成企业数字化趋势与CRM研究报告

系统集成是一种新型的服务方式&#xff0c;是企业进行信息传递和共享的通用型智能工具&#xff0c;在企业系统优化升级、流程的打通和重构、数据的收集与分析应用&#xff0c;以及IT运维与安全保障等方面起着降低成本&#xff0c;提高效率的重要作用。 整体来看&#xff0c;近…

【乐吾乐大屏可视化组态编辑器】事件交互-场景交互

场景交互 在线使用&#xff1a;https://v.le5le.com/ 乐吾乐大屏可视化可以实现大屏页面与内嵌2d/3d场景相互通信&#xff0c;底层原理是利用了iframe通过postMessage发送消息。 下面以2d场景为例&#xff0c;实现步骤如下&#xff1a; 1. 首先配置场景2&#xff08;被嵌入…

【分享】格力手机色界G0245D 刷REC、root、 救砖、第三方rom教程和资源

开门见山 帮别人弄了一台 格力G0245D&#xff0c;把找到的资源和教程分享一下 教程 这个写的很详细了格力手机色界G0245D-Root-最简指南 不过教程里刷rec这一步漏了加上电源键&#xff0c;加上就行了。 附加参考&#xff1a;格力手机2刷机 格力手机二代刷机 GREE G0215D刷机…

STM32如何设置自动代码提示?

首先&#xff1a; 点击Window--->Preferences 进来之后在左上方输入keys&#xff0c;然后点击Keys&#xff0c;在Scheme下方那一栏中输入Content Assist 然后点击Content Assist--->在下方Binding栏中选择Tab--->Apply--->Apply and Close 设置完成&#xff0c;测…

hutool发邮件功能如何配置SMTP服务器参数?

hutool发邮件的教程指南&#xff1f;hutool发邮件性能优化方法&#xff1f; Hutool作为一个轻量级的Java工具库&#xff0c;其邮件发送功能因其简单易用而受到广泛关注。AokSend将详细介绍如何通过配置SMTP服务器参数来实现Hutool发邮件的功能。 hutool发邮件&#xff1a;优势…

为什么要用数字化营销管理平台?

数字化营销管理平台是一种利用数字技术来整合和优化营销流程的工具。它能够帮助企业更高效地进行市场推广、客户关系管理以及销售活动。 一、主要功能 1.数据整合与分析 整合多渠道数据&#xff0c;包括网站流量、社交媒体互动、电子邮件营销反馈等。通过数据分析&#xff0…

k8s高版本(1,28)部署NodePort模式下的ingress-nginx的详细过程及应用案例

文章目录 前言环境ingress安装应用案例(ingress-http案例&#xff1a; 基于名称的负载均衡) 前言 这个是nodeport模式下的&#xff0c;如果需要loadbalancer模式下的&#xff0c;看看博主下面以前的博客 链接: k8s学习–负载均衡器matelLB的详细解释与安装 链接: k8s学习–ing…

RTA-VRTE适配Orin

RTA-VRTE适配Orin sudo minicom -w -D /dev/ttyACM0 用户名 nvidia密码 123456底下的的rj45 ,对应的是eqos_0, (本次porting使用该接口)底下的的DEBUG(USB Micro-B)串口连接(本次porting使用该接口)上侧边的rj45,对应的是mgbe0_0#设置Orin的IP和默认网卡eqos_0

【机器学习】随机森林

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、随机森林定义 随机森林&#xff08;Random Forest, RF&#xff09;是一种由 决策树 构成的 集成算法 &#xff0c;采用的是 Bagging 方法&#xff0c;他在…

开发小运维-常用Linux资源监控命令

文章目录 简介常用命令/proc/meminfo&#xff08;内存&#xff09;free&#xff08;内存信息&#xff09;top&#xff08;进程动态&#xff09;df &#xff08;磁盘信息&#xff09;du&#xff08;磁盘信息&#xff09;ps&#xff08;进程状态&#xff09;vmstat&#xff08;内…

Tita的OKR :销售部 OKR案例

销售集团目标 – OKR示例 目标&#xff1a;为我们的销售团队招募世界级精英 主要成果&#xff1a; KR1&#xff1a;在10月底之前雇用10个新的AE KR2&#xff1a;在11月底之前雇用20个新SDR KR3&#xff1a;到10月底雇用5名新的销售经理 KR4&#xff1a;维持 4&#xff1a;1的…

Linux date命令

概述 date 命令用于显示或设置系统的时间与日期&#xff0c;语法格式为&#xff1a;“date [指定的格式]”。用户只需在强大的 date 命令后输入以“”号开头的参数&#xff0c;即可按照指定格式来输出系统的时间或日期。 [rootlocalroot ~]# uname -a #当前系统 Linux…

[vue] pdf.js / vue-pdf 文件花屏问题

vue-pdf内核也是pdf.js&#xff0c;修改方式一样 在pdf.worker.js中加入几行代码&#xff0c;追加到”precinct.zeroBitPlanesTree zeroBitPlanesTree;“之后。 for (var l 0; l < layerNumber; l) {if (readBits(1) ! 0) {throw new JpxError("Invalid tag tree&qu…

网络编程/在哪些场景中不必要进行网络字节序转换? Windows Sockets: Byte Ordering

文章目录 概述字节序必须转换字节序的的情况不必转换字节序的的情况字节序转换的例程字节序转换函数字节序转换可以不生硬字节序和位序 概述 本文主要讲述了在哪些场景下必须要进行大小端字节序转换&#xff0c;在哪些场景下可以不用进行大小端字节序转换&#xff0c;IP和端口…