HTML飘落的花瓣

目录

写在前面

HTML​​​​​​​简介

完整代码

代码分析

系列推荐

写在最后


写在前面

本期小编给大家推荐HTML实现的飘落的花瓣,无需安装软件,直接下载即可打开~

HTML​​​​​​​简介

HTML(Hypertext Markup Language)是一种用于创建网页的标记语言。它由一系列标签组成,这些标签描述了网页上的内容和结构。HTML中的标签以尖括号包围,通常成对出现,包括起始标签和结束标签,它们之间包含内容。HTML文档通常以<html>标签开始,以</html>标签结束。常见的标签包括<head>用于定义文档的头部信息,<title>用于指定标题,<body>用于定义文档的主体内容等。通过使用不同的标签和属性,开发人员可以创建出多样化且丰富的网页内容,包括文本、图像、链接、表格等。HTML的语法相对简单,易于学习和使用,是构建网页的基础。随着技术的发展,HTML也在不断更新,最新版本为HTML5,提供了更多功能和语义化标签,使得网页开发更加灵活和可靠。

完整代码

<!DOCTYPE HTML>
<HTML>

<TITLE>飘落的花瓣</TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
    html,
    body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
    }

    .container {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        background-color: #000000;
    }
</style>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</HEAD>

<BODY>

    <div id="jsi-cherry-container" class="container"></div>
    <script>
        var RENDERER = {
            INIT_CHERRY_BLOSSOM_COUNT: 30,
            MAX_ADDING_INTERVAL: 10,

            init: function () {
                this.setParameters();
                this.reconstructMethods();
                this.createCherries();
                this.render();
            },
            setParameters: function () {
                this.$container = $('#jsi-cherry-container');
                this.width = this.$container.width();
                this.height = this.$container.height();
                this.context = $('<canvas />').attr({ width: this.width, height: this.height }).appendTo(this.$container).get(0).getContext('2d');
                this.cherries = [];
                this.maxAddingInterval = Math.round(this.MAX_ADDING_INTERVAL * 1000 / this.width);
                this.addingInterval = this.maxAddingInterval;
            },
            reconstructMethods: function () {
                this.render = this.render.bind(this);
            },
            createCherries: function () {
                for (var i = 0, length = Math.round(this.INIT_CHERRY_BLOSSOM_COUNT * this.width / 1000); i < length; i++) {
                    this.cherries.push(new CHERRY_BLOSSOM(this, true));
                }
            },
            render: function () {
                requestAnimationFrame(this.render);
                this.context.clearRect(0, 0, this.width, this.height);

                this.cherries.sort(function (cherry1, cherry2) {
                    return cherry1.z - cherry2.z;
                });
                for (var i = this.cherries.length - 1; i >= 0; i--) {
                    if (!this.cherries[i].render(this.context)) {
                        this.cherries.splice(i, 1);
                    }
                }
                if (--this.addingInterval == 0) {
                    this.addingInterval = this.maxAddingInterval;
                    this.cherries.push(new CHERRY_BLOSSOM(this, false));
                }
            }
        };
        var CHERRY_BLOSSOM = function (renderer, isRandom) {
            this.renderer = renderer;
            this.init(isRandom);
        };
        CHERRY_BLOSSOM.prototype = {
            FOCUS_POSITION: 300,
            FAR_LIMIT: 600,
            MAX_RIPPLE_COUNT: 100,
            RIPPLE_RADIUS: 100,
            SURFACE_RATE: 0.5,
            SINK_OFFSET: 20,

            init: function (isRandom) {
                this.x = this.getRandomValue(-this.renderer.width, this.renderer.width);
                this.y = isRandom ? this.getRandomValue(0, this.renderer.height) : this.renderer.height * 1.5;
                this.z = this.getRandomValue(0, this.FAR_LIMIT);
                this.vx = this.getRandomValue(-2, 2);
                this.vy = -2;
                this.theta = this.getRandomValue(0, Math.PI * 2);
                this.phi = this.getRandomValue(0, Math.PI * 2);
                this.psi = 0;
                this.dpsi = this.getRandomValue(Math.PI / 600, Math.PI / 300);
                this.opacity = 0;
                this.endTheta = false;
                this.endPhi = false;
                this.rippleCount = 0;

                var axis = this.getAxis(),
                    theta = this.theta + Math.ceil(-(this.y + this.renderer.height * this.SURFACE_RATE) / this.vy) * Math.PI / 500;
                theta %= Math.PI * 2;

                this.offsetY = 40 * ((theta <= Math.PI / 2 || theta >= Math.PI * 3 / 2) ? -1 : 1);
                this.thresholdY = this.renderer.height / 2 + this.renderer.height * this.SURFACE_RATE * axis.rate;
                this.entityColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
                this.entityColor.addColorStop(0, 'hsl(330, 70%, ' + 50 * (0.3 + axis.rate) + '%)');
                this.entityColor.addColorStop(0.05, 'hsl(330, 40%,' + 55 * (0.3 + axis.rate) + '%)');
                this.entityColor.addColorStop(1, 'hsl(330, 20%, ' + 70 * (0.3 + axis.rate) + '%)');
                this.shadowColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
                this.shadowColor.addColorStop(0, 'hsl(330, 40%, ' + 30 * (0.3 + axis.rate) + '%)');
                this.shadowColor.addColorStop(0.05, 'hsl(330, 40%,' + 30 * (0.3 + axis.rate) + '%)');
                this.shadowColor.addColorStop(1, 'hsl(330, 20%, ' + 40 * (0.3 + axis.rate) + '%)');
            },
            getRandomValue: function (min, max) {
                return min + (max - min) * Math.random();
            },
            getAxis: function () {
                var rate = this.FOCUS_POSITION / (this.z + this.FOCUS_POSITION),
                    x = this.renderer.width / 2 + this.x * rate,
                    y = this.renderer.height / 2 - this.y * rate;
                return { rate: rate, x: x, y: y };
            },
            renderCherry: function (context, axis) {
                context.beginPath();
                context.moveTo(0, 40);
                context.bezierCurveTo(-60, 20, -10, -60, 0, -20);
                context.bezierCurveTo(10, -60, 60, 20, 0, 40);
                context.fill();

                for (var i = -4; i < 4; i++) {
                    context.beginPath();
                    context.moveTo(0, 40);
                    context.quadraticCurveTo(i * 12, 10, i * 4, -24 + Math.abs(i) * 2);
                    context.stroke();
                }
            },
            render: function (context) {
                var axis = this.getAxis();

                if (axis.y == this.thresholdY && this.rippleCount < this.MAX_RIPPLE_COUNT) {
                    context.save();
                    context.lineWidth = 2;
                    context.strokeStyle = 'hsla(0, 0%, 100%, ' + (this.MAX_RIPPLE_COUNT - this.rippleCount) / this.MAX_RIPPLE_COUNT + ')';
                    context.translate(axis.x + this.offsetY * axis.rate * (this.theta <= Math.PI ? -1 : 1), axis.y);
                    context.scale(1, 0.3);
                    context.beginPath();
                    context.arc(0, 0, this.rippleCount / this.MAX_RIPPLE_COUNT * this.RIPPLE_RADIUS * axis.rate, 0, Math.PI * 2, false);
                    context.stroke();
                    context.restore();
                    this.rippleCount++;
                }
                if (axis.y < this.thresholdY || (!this.endTheta || !this.endPhi)) {
                    if (this.y <= 0) {
                        this.opacity = Math.min(this.opacity + 0.01, 1);
                    }
                    context.save();
                    context.globalAlpha = this.opacity;
                    context.fillStyle = this.shadowColor;
                    context.strokeStyle = 'hsl(330, 30%,' + 40 * (0.3 + axis.rate) + '%)';
                    context.translate(axis.x, Math.max(axis.y, this.thresholdY + this.thresholdY - axis.y));
                    context.rotate(Math.PI - this.theta);
                    context.scale(axis.rate * -Math.sin(this.phi), axis.rate);
                    context.translate(0, this.offsetY);
                    this.renderCherry(context, axis);
                    context.restore();
                }
                context.save();
                context.fillStyle = this.entityColor;
                context.strokeStyle = 'hsl(330, 40%,' + 70 * (0.3 + axis.rate) + '%)';
                context.translate(axis.x, axis.y + Math.abs(this.SINK_OFFSET * Math.sin(this.psi) * axis.rate));
                context.rotate(this.theta);
                context.scale(axis.rate * Math.sin(this.phi), axis.rate);
                context.translate(0, this.offsetY);
                this.renderCherry(context, axis);
                context.restore();

                if (this.y <= -this.renderer.height / 4) {
                    if (!this.endTheta) {
                        for (var theta = Math.PI / 2, end = Math.PI * 3 / 2; theta <= end; theta += Math.PI) {
                            if (this.theta < theta && this.theta + Math.PI / 200 > theta) {
                                this.theta = theta;
                                this.endTheta = true;
                                break;
                            }
                        }
                    }
                    if (!this.endPhi) {
                        for (var phi = Math.PI / 8, end = Math.PI * 7 / 8; phi <= end; phi += Math.PI * 3 / 4) {
                            if (this.phi < phi && this.phi + Math.PI / 200 > phi) {
                                this.phi = Math.PI / 8;
                                this.endPhi = true;
                                break;
                            }
                        }
                    }
                }
                if (!this.endTheta) {
                    if (axis.y == this.thresholdY) {
                        this.theta += Math.PI / 200 * ((this.theta < Math.PI / 2 || (this.theta >= Math.PI && this.theta < Math.PI * 3 / 2)) ? 1 : -1);
                    } else {
                        this.theta += Math.PI / 500;
                    }
                    this.theta %= Math.PI * 2;
                }
                if (this.endPhi) {
                    if (this.rippleCount == this.MAX_RIPPLE_COUNT) {
                        this.psi += this.dpsi;
                        this.psi %= Math.PI * 2;
                    }
                } else {
                    this.phi += Math.PI / ((axis.y == this.thresholdY) ? 200 : 500);
                    this.phi %= Math.PI;
                }
                if (this.y <= -this.renderer.height * this.SURFACE_RATE) {
                    this.x += 2;
                    this.y = -this.renderer.height * this.SURFACE_RATE;
                } else {
                    this.x += this.vx;
                    this.y += this.vy;
                }
                return this.z > -this.FOCUS_POSITION && this.z < this.FAR_LIMIT && this.x < this.renderer.width * 1.5;
            }
        };
        $(function () {
            RENDERER.init();
        });
    </script>
</BODY>

</HTML>

代码分析

这段代码是一个HTML页面,其中包含一个canvas元素和相关的JavaScript代码。这个页面创建了一个飘落花瓣的动画效果。具体分析如下:

1. 首先定义了HTML结构,`<div id="jsi-cherry-container"></div>` 是一个用于承载花瓣动画的容器。

2. CSS样式部分设置了整个页面和容器的宽高为100%,且隐藏了滚动条。

3. JavaScript部分首先引入了jQuery库(虽然在这个示例中没有直接使用)。

4. RENDERER对象是动画的核心逻辑,它包含了初始化、设置参数、重构方法、创建花瓣以及渲染循环等方法。在init方法中,通过setParameters设定画布大小、获取容器元素、创建2D渲染上下文并初始化花瓣数组。createCherries方法用于生成初始数量的花瓣对象。render方法是动画渲染循环,每一帧会清除画布内容,重新排序花瓣,然后逐一渲染每个花瓣,并按照一定间隔添加新的花瓣。

5. CHERRY_BLOSSOM类代表单个花瓣,其构造函数接受一个RENDERER对象作为参数,并初始化花瓣的各种属性,包括位置、速度、颜色渐变等。该类中的init方法用于随机或指定方式初始化花瓣状态,render方法则负责绘制花瓣及涟漪效果。

6. 整个动画模拟了花瓣从画面顶部飘落并在接触到水面时产生涟漪的效果,通过不断更新花瓣的位置和角度,在canvas上绘制出动态变化的花瓣图像。

系列推荐

序号目录直达链接
1HTML实现3D相册https://want595.blog.csdn.net/article/details/138652869
2HTML元素周期表https://want595.blog.csdn.net/article/details/138653653
3HTML黑客帝国字母雨https://want595.blog.csdn.net/article/details/138654054
4HTML五彩缤纷的爱心https://want595.blog.csdn.net/article/details/138654581
5HTML飘落的花瓣https://want595.blog.csdn.net/article/details/138785324
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

写在最后

我是一只有趣的兔子,感谢你的喜欢!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32学习和实践笔记(28):printf重定向实验

1.printf重定向简介 在C语言中printf函数里&#xff0c;默认输出设备是显示器&#xff0c;如果想要用这个函数将输出结果到串口或者LCD上显示&#xff0c;就必须重定义标准库函数里中printf函数调用的与输出设备相关的函数。 比如要使用printf输出到串口&#xff0c;需要先将f…

灌区信息化管理平台软件如何建设?

随着科技的飞速发展&#xff0c;数字孪生技术正逐渐渗透到各个行业领域&#xff0c;其中&#xff0c;数字孪生灌区的建设成为了智慧水利的重要组成部分。那么&#xff0c;究竟如何进行数字孪生灌区信息化管理平台软件建设呢&#xff1f;本文将为您揭开这一神秘面纱&#xff0c;…

引用和实体完整性

本文将详细讲解在数据库服务器级具有引用和实体完整性的好处&#xff0c;包括如何在字段中设置默认值、检查约束和引用约束&#xff0c;以及在何时发生约束检查。通过遵循这些指导原则&#xff0c;可以确保数据的一致性和准确性。 1.完整性 完整性指数据库中数据的准确性或正确…

【Linux线程(二)】线程互斥和同步

前言&#xff1a; 在上一篇博客中&#xff0c;我们讲解了什么是线程以及如何对线程进行控制&#xff0c;那么了解了这些&#xff0c;我们就可以在程序中创建多线程了&#xff0c;可是多线程往往会带有许多问题&#xff0c;比如竞态条件、死锁、数据竞争、内存泄漏等问题&#…

福建聚鼎:做装饰画到底能不能赚钱

在探讨做装饰画能否成为盈利的行当之前&#xff0c;我们必须认识到任何一门艺术或手工的价值并非仅仅取决于其直接的经济收益。艺术创作本身就是一种文化传承和个人情感表达的方式&#xff0c;它对创作者和社会都有着不可估量的精神价值。然而&#xff0c;将话题限定在经济回报…

【机器学习300问】81、什么是动量梯度下降算法?

动量梯度下降算法&#xff08;Momentum&#xff09;是利用指数加权移动平均的思想来实现梯度下降的算法。让我们先来回顾一下基础的梯度下降方法以及看看它有哪些不足之处。接着引出动量梯度下降算法&#xff0c;在理解了它的原理后看看它是如何规避之前方法的不足的。 如果不知…

Java开发大厂面试第01讲:String 的特点及其重要的方法都有哪些?

几乎所有的 Java 面试都是以 String 开始的&#xff0c;如果第一个问题没有回答好&#xff0c;则会给面试官留下非常不好的第一印象&#xff0c;而糟糕的第一印象则会直接影响到自己的面试结果&#xff0c;就好像刚破壳的小鹅一样&#xff0c;会把第一眼看到的动物当成自己的母…

制药行业新突破:CANOpen转PROFINET网关配置案例解析

在药品制造工业环境中&#xff0c;实现CanOpen转Profinet协议之间转换的网关配置是一个关键过程&#xff0c;确保了不同通信协议的设备能够互相协作。以开疆智能CanOpen转Profinet网关为例&#xff0c;以下是其配置流程&#xff1a;首先安装CanOpen转Profinet网关的配置软件&am…

Linux禁用危险命令和防止误操作

禁用rm命令 编辑/etc/profile文件&#xff0c;结尾添加 ###### rm prevent ###### alias rmecho can not use rm command使用source命令生效 source /etc/profile效果 使用mv命令代替rm命令 将需要删除的文件移动到特定的目录&#xff0c;比如/home/sharedir/ 在.bashrc目…

波卡 2024 一季度报告:XCM 创下历史新高,JAM 链将引领 Polkadot 2.0 新风向

作者&#xff1a;Nicholas Garcia&#xff5c;Messari 研究分析师 编译&#xff1a;OneBlock 原文&#xff1a;https://messari.io/report/state-of-polkadot-q1-2024 近期&#xff0c;Messari Crypto 发布了 Polkadot 2024 年 Q1 状况的数据报告。OneBlock 为你梳理了本篇报…

python批量为图片做灰度处理

欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 二.代码 三.使用 四.总结

MES管理系统在柔性制造中有何重要作用

在当今这个瞬息万变的商业环境中&#xff0c;制造业正经历着一场前所未有的转型。消费者需求的多样化和市场动态的快速变化要求企业必须具备高度的灵活性和适应性。为了应对这些挑战&#xff0c;柔性制造策略应运而生&#xff0c;它以其快速响应和灵活调整的能力&#xff0c;成…

vue3中的watch侦听器

在有些情况下&#xff0c;我们需要在状态变化时执行一些“副作用”&#xff1a;例如更改 DOM &#xff0c;或是根据异步操作的结果去修改另一处的状态。在组合式 API 中&#xff0c;我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数。 watch 函数可以侦听被 ref…

计算机的一些基础知识分享

windows操作系统中&#xff0c;用于查看当前文件下的目录是&#xff1f; 在Windows操作系统中&#xff0c;如果您想要查看当前文件夹下的目录&#xff0c;您可以使用命令提示符&#xff08;CMD&#xff09;或PowerShell。在这些环境中&#xff0c;可以使用以下命令&#xff1a;…

bmi088-linux驱动(I2C)

电气特性&#xff1a; 在正常工作时&#xff0c;gyro 工作电流为5mA&#xff0c;acc 工作电流为150uA。 SPI 时钟和数据电平范围 0 -3.6 结构框图如下&#xff1a; 硬件连接图如下&#xff1a; note&#xff1a; 1. 通过PS引脚选择通讯协议&#xff0c;上拉引脚则选择的是I2C…

HCIP的学习(16)

BGP的状态机 ​ OSPF的状态机是在描述整个协议的完整工作过程&#xff0c;而BGP的状态机仅描述的是对等体关系建立过程中的状态变化。-----因为BGP将邻居建立过程以及BGP路由收发过程完全隔离。 ​ IGP协议在启动后&#xff0c;需要通过network命令激活接口&#xff0c;从而使…

企业运维背后的故事:TASKCTL带你了解日常工作与技术演进

今天&#xff0c;作为一名经验丰富、从业多年经常与运维人员打交道的人&#xff0c;我想与大家聊聊运维的日常工作、部门协调以及未来发展&#xff0c;希望能为即将转行或正在从事运维工作的你&#xff0c;提供一些新的视角和启发。 运维的日常工作&#xff1a;挑战与乐趣并存 …

朱啸虎:AI应用明年肯定大爆发;第3款爆火AI游戏出现了;AI应用定价策略「不能说的秘密」;人类数据不够用了怎么办 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; 1. 换你来当爹&#xff1a;国内第3款爆火出圈的AI游戏应用&#xff0c;hhh 太搞笑了 周末的时候&#xff0c;社群里伙伴们开始玩一款「换你来当爹」的…

[Java EE] 多线程(九):JUC剩余部分与线程安全的集合类(多线程完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

群晖 Synology DSM7 过热关机解决方法

最近已经提示我过热关机过两次了&#xff0c;这两次一次是用虚拟机&#xff0c;一次是批量使用Synology Photos批量上传照片&#xff1a; 但是我没有对主机进行任何的位置移动以及硬件修改操作&#xff0c;散热环境没有发生变化。以前使用从来没有出现过这个问题&#xff0c;同…