爱心动画代码HTML5

news2024/9/19 19:45:53

这段代码是一个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 pool
                particles = 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 queue
                firstFree++;
                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 particles
                if (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 particles
                while (particles[firstActive].age >= duration && firstActive != firstFree) {
                    firstActive++;
                    if (firstActive == particles.length) firstActive = 0;
                }


            };
            ParticlePool.prototype.draw = function (context, image) {
                // draw active particles
                if (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/sec
                time;

            // 根据给定的参数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 path
                function 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 path
                context.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 fill
                context.fillStyle = '#ea80b0';
                context.fill();
                // create the image
                var image = new Image();
                image.src = canvas.toDataURL();
                return image;
            })();

            // 渲染函数,用于每一帧的动画绘制
            function render() {
                // next animation frame
                requestAnimationFrame(render);

                // update time
                var newTime = new Date().getTime() / 1000,
                    deltaTime = newTime - (time || newTime);
                time = newTime;

                // clear canvas
                context.clearRect(0, 0, canvas.width, canvas.height);

                // create new particles
                var 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 particles
                particles.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.coloradmin.cn/o/2055005.html

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

相关文章

部署Nginx负载均衡+动静分离的群集

目录 一、Nginx应用 二、正向代理与反向代理 1.1正向代理 1.2反向代理 三、负载均衡 1.轮询&#xff08;Round Robin&#xff09; 2.最小连接数 3.IP hash: 4.加权轮询 5.最少事件算法 6.一致性hash 一、Nginx应用 Nginx是一款非常优秀的HTTP服务器软件 支持高达50 …

【生日视频制作】洪崖洞高大楼AE模板修改文字软件生成器教程特效素材【AE模板】

洪崖洞企业高大楼生日视频制作教程AE模板改文字特效生成器素材 怎么如何做的【生日视频制作】洪崖洞企业高大楼AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件下载AE模板把AE模板导入AE软件修改图片或文字渲染出视频

【JAVA八股文】持续更新中...

【-------------数据类型------------】 一、基本类型、包装类型 基本类型&#xff1a;整型&#xff08;byte short int long &#xff09;浮点型&#xff08;float double&#xff09;布尔型&#xff08;boolean&#xff09; 字符型&#xff…

【联想电脑】:使用拓展坞后转接HDMI,无法识别显示屏

项目场景&#xff1a; 作为一个嵌入式软件开发者&#xff0c;有两个外接屏幕&#xff0c;不足为奇。 但是在今天的使用电脑过程中&#xff0c;出现了接了一个拓展坞上面有HDMI接口&#xff0c;但是HDMI接口接上外接显示屏的时候电脑无法识别到&#xff0c;导致只有电脑直连的HD…

安装Pentaho Data Integration并启动

“pdi-ce-9.3.0.0-428.zip”包在 “/opt/software/”目录下。 步骤详情 1. 解压zip包2. 启动 Pentaho Data Integration PDI&#xff08;Kettle&#xff09; GUI 界面 1. 解压zip包 因为 Kettle 是绿色软件工具&#xff0c;开箱即用&#xff0c;无须安装。首先进入“/opt/soft…

ansible 中剧本的书写与运行

1.更改配置文件vim /etc/ansible/hosts 2.测试m0主机与s0、s1、s2&#xff0c;之间可以ping通 [rootm0 ansible]# ansible group02 -m ping 3.书写脚本文件 [rootm0 ~]# vim test0001.yml ​ --- - hosts: group02remote_user: roottasks: ​- name:…

【Qt】常用控件QLabel

常用控件QLabel QLabel可以用来显示文本和图片。 QLabel的属性 其核心属性如下&#xff1a; 属性说明 text QLabel 中的⽂本 textFormat ⽂本的格式. Qt::PlainText 纯⽂本Qt::RichText 富⽂本(⽀持 html 标签)Qt::MarkdownText markdown 格式Qt::AutoText 根据⽂本内容…

uniapp 页面跳转传参:父页面监听子页面传过来的数据

父页面 监听events事件 uni.navigateTo({url: "/components/watermark-camera",events: { // 重点重点重点重点重点重点重点重点getImages(data) { // 接收子页面抛出的 getImages 事件console.log("水印相机的照片&#xff1a;", data)}}})子页面 const …

人工智能和机器学习 3(复旦大学计算机科学与技术实践工作站)python机器学习、Pytorch库入门、d2l学习+<机器学习、神经网络————原理、理论>

前言 安装 — 动手学深度学习 2.0.0 documentation (d2l.ai)https://zh.d2l.ai/chapter_installation/index.html 安装 我们需要配置一个环境来运行 Python、Jupyter Notebook、相关库以及运行本书所需的代码&#xff0c;以快速入门并获得动手学习经验。 安装 Miniconda 最…

【css】水平对齐方式(justify、text-align、display: flex;)

一、justify 完整的属性名是 justify-contentjustify-content 用于定义位于同一行的项目在主轴&#xff08;通常是水平方向&#xff09;上的对齐方式。 center &#xff1a;居中start : 起始位置对齐&#xff08;左对齐&#xff09;end : 结束位置对齐&#xff08;右对齐&…

使用 LlamaIndex 中的 Relik 进行实体链接和关系提取

从文本构建知识图谱长期以来一直是一个令人着迷的研究领域。随着大型语言模型 (LLM) 的出现&#xff0c;该领域获得了更多主流关注。然而&#xff0c;LLM 的成本可能相当高。另一种方法是微调较小的模型&#xff0c;这种方法得到了学术研究的支持&#xff0c;可以产生更有效的解…

无线领夹麦克风哪个牌子好?最好的无线麦克风品牌排行推荐

伴随着智能手机的不断发展&#xff0c;手机不单单只是承担着联系的作用&#xff0c;凭借着小巧、出色拍摄体验等&#xff0c;成为了绝大部分朋友记录生活的绝佳选择&#xff0c;例如录制VLog、短视频等等。不过录制视频必然需要考虑到收音问题&#xff0c;因为在实际录制过程中…

Java面试八股之什么是消息队列的高并发缓冲

什么是消息队列的高并发缓冲 消息队列的高并发缓冲是指在处理大量并发请求时&#xff0c;通过消息队列来平滑处理请求的一种机制。这种机制可以帮助系统在高并发场景下保持稳定性和性能。 高并发缓冲的核心思想&#xff1a; 解耦&#xff1a; 消息队列作为一个中间层&#…

树莓派5 笔记26:ollama大型语言模型_中文输入法_Python_espeak文字转语音

今日继续学习树莓派5 8G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下&#xff1a; 下载大语言模型&#xff0c;下载中文输入法&#…

HTML+CSS+JS实现商城首页[web课设代码+模块说明+效果图]

系列文章目录 1.Web前端大作业htmlcss静态页面–掌****有限公司 2.Web前端大作业起点小说静态页面 3.Web前端大作业网易云页面 4.Web前端大作业商城页面 5.Web前端大作业游戏官网页面 6.Web前端大作业网上商城页面 7.HTMLCSS淘宝首页[web课设代码模块说明效果图] 8.HTMLCSSJS实…

Linux | 深入探究Linux进程控制:从fork函数到进程等待再到进程替换

目录 1、进程的创建&#xff1a;fork函数 2、父子进程的奇怪现象&#xff1a;为什么同一个地址有不同的值&#xff1f;——区分内存的虚拟地址和物理地址 代码&#xff1a;利用fork函数的返回值进行父子进程分流&#xff0c;执行不同的代码块 虚拟地址和物理地址&#xff1…

selenium学习记录

1、初识selenium 概述&#xff1a; Selenium是一个Web的自动化测试工具&#xff0c;最初是为网站自动化测试而开发的&#xff0c;类型像我们玩游戏用的按键精灵&#xff0c;可以按指定的命令自动操作&#xff0c;不同是Selenium 可以直接运行在浏览器上&#xff0c;它支持所有…

【java】RuoYiBootstrap多模块版本-登陆请求流程解析

登陆请求流程逻辑图 Created with Raphal 2.3.0 &#xff08;1&#xff09;登陆流程解析 &#xff08;2&#xff09;【接下来所有业务都受ShiroConfig配置所过滤】 模块&#xff1a;ruoyi-framework 位置&#xff1a;src/main/java 包名&#xff1a;com.ruoyi.framework.config…

【机器学习】CNN的数学基础

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 CNN的数学基础1. 引言2. 卷积运算2.1 连续卷积2.2 离散卷积2.3 互相关 3. 激活函…

【html+css 绚丽Loading】 - 000007 虚空灵瞳

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…