用HTML、CSS和JS打造绚丽的雪花飘落效果

news2024/12/27 12:48:31

目录

一、程序代码

二、代码原理

三、运行效果


一、程序代码

<!DOCTYPE html>
<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=GBK">
	<style>
		* {
			margin: 0;
			padding: 0;
		}

		#box {
			width: 100vw;
			height: 100vh;
			padding: 3px;
			position: absolute;
			background: black;
		}
	</style>
</head>

<body>
	<div id="box">

	</div>
</body>

<script>
	(function () {
		var screenWidth = screen.availWidth; // 获取屏幕宽度
		var screenHeight = screen.availHeight; // 获取屏幕高度
		var speed = 1; // 雪花下落的速度

		function Snow(size, downSize) {
			this.box = document.getElementById("box"); // 获取容器元素
			this.size = size; // 雪花数量
			this.downSize = downSize || 10; // 每次落下的雪花数量,默认为10个
			this.item = []; // 雪花元素数组
			this.init(); // 初始化
			this.start(); // 开始下雪
		}

		// 获取相关随机数据的方法
		Snow.prototype.getRandomThings = function (type) {
			var res;
			if (type == 'left') { // 初始的left
				res = Math.round(Math.random() * (screenWidth - 30 - 10)) + 10; // 随机生成left值
				Math.random() > 0.8 ? (res = -res) : null; // 80%的概率使左边的雪花出现在左侧(left为负值)
			} else if (type == 'top') { // 初始的top
				res = -(Math.round(Math.random() * (50 - 40)) + 40); // 随机生成top值,负值使雪花在屏幕上方
			} else if (type == 'incre') { // 向下的速度
				res = Math.random() * (4 - 1) + 1; // 随机生成向下的速度
			} else if (type == 'increLeft') { // 向右的速度
				res = Math.random() * (0.8 - 0.5) + 0.5; // 随机生成向右的速度
			} else { // 雪花的大小
				res = Math.round(Math.random() * (30 - 10)) + 10; // 随机生成雪花的大小
			}
			return res;
		}

		Snow.prototype.init = function () {
			this.box.style.width = screenWidth + 'px'; // 设置容器宽度为屏幕宽度
			this.box.style.height = screenHeight + 'px'; // 设置容器高度为屏幕高度
			var fragment = document.createDocumentFragment(); // 创建文档片段,用于性能优化
			for (var i = 0; i < this.size; i++) { // 创建雪花元素
				var left = this.getRandomThings('left'); // 获取随机的left值
				var top = this.getRandomThings('top'); // 获取随机的top值
				var snowSize = this.getRandomThings('size'); // 获取随机的雪花大小
				var snow = document.createElement("div"); // 创建雪花元素
				snow.style.cssText = 'position:absolute;color:#FFFFFF;'; // 设置元素样式
				snow.style['font-size'] = snowSize + 'px'; // 设置字体大小
				snow.style.left = left + 'px'; // 设置left值
				snow.style.top = top + 'px'; // 设置top值
				snow.innerHTML = '&#10052'; // 设置雪花图标(Unicode编码)
				this.item.push(snow); // 添加到雪花元素数组中
				fragment.appendChild(snow); // 添加到文档片段中
			}
			box.appendChild(fragment); // 将文档片段添加到容器中
		}

		Snow.prototype.start = function () {
			var that = this;
			var num = 0;
			for (var i = 0; i < this.size; i++) { // 遍历雪花元素数组
				var snow = this.item[i];
				if ((i + 1) % this.downSize == 0) { // 每downSize个雪花一组,控制下落速度
					num++;
				}
				(function (s, n) { // 使用闭包保存snow和num的值
					setTimeout(function () { // 定时器,实现雪花分批下落
						that.doStart(s); // 调用doStart方法使雪花开始下落
					}, 1000 * n) // 每隔n秒下落一组雪花
				})(snow, num)
			}
		}

		// 针对每个雪花的定时处理
		Snow.prototype.doStart = function (snow) {
			var that = this;
			(function (s) {
				var increTop = that.getRandomThings('incre'); // 获取向下的速度
				var increLeft = that.getRandomThings('increLeft'); // 获取向右的速度
				var x = parseInt(getStyle(s, 'left')), y = parseInt(getStyle(s, 'top')); // 获取当前的left和top值

				if (s.timmer) return; // 如果定时器已存在,则不执行后续代码
				s.timmer = setInterval(function () { // 设置定时器,使雪花动起来
					// 超过右边或者底部重新开始
					if (y > (screenHeight - 5) || x > (screenWidth - 30)) {
						// 重新回到天上开始往下
						increTop = that.getRandomThings('incre');
						increLeft = that.getRandomThings('increLeft');

						// 重新随机属性
						var left = that.getRandomThings('left');
						var top = that.getRandomThings('top');
						var snowSize = that.getRandomThings('size');
						s.style.left = left + 'px';
						s.style.top = top + 'px';
						s.style['font-size'] = snowSize + 'px';
						y = top;
						x = left;
						n = 0;

						return;
					}

					// 加上系数,当随机数大于0.5时速度加快,小于0.5时速度减慢,形成飘动效果
					x += Math.random() > 0.5 ? increLeft * 1.1 : increLeft * 0.9;
					y += Math.random() > 0.5 ? increTop * 1.1 : increTop * 0.9;

					// 设置left和top值使雪花动起来
					s.style.left = x + 'px';
					s.style.top = y + 'px';
				}, speed); // 每隔speed毫秒执行一次定时器中的代码
			})(snow)
		}

		// 获取元素的样式值
		function getStyle(obj, prop) {
			var prevComputedStyle = document.defaultView ? document.defaultView.getComputedStyle(obj, null) : obj.currentStyle;
			return prevComputedStyle[prop];
		}

		new Snow(300, 30); // 创建一个Snow对象,传入雪花数量和每批下落的雪花数量
	})()

</script>

</html>

二、代码原理

这段代码主要通过JavaScript来操作DOM元素,实现了一个下雪的效果。首先,通过CSS样式设置整个页面的背景为黑色,并且创建一个id为"box"的容器元素用于容纳雪花。

接着,使用JavaScript代码自执行函数来封装雪花的相关逻辑。在这个函数中,获取屏幕的宽度和高度,并定义了雪花下落的速度。

然后,定义了一个Snow对象构造函数,用于创建雪花。构造函数接受两个参数,分别是雪花的数量和每批下落的雪花数量。在构造函数中,首先通过getElementById方法获取到容器元素,并设置容器的宽度和高度与屏幕一致。然后,使用for循环创建指定数量的雪花元素,通过随机数设置雪花的初始位置、大小和样式,并将雪花元素添加到数组item和文档片段中。最后,将文档片段添加到容器中。

接着,在Snow对象的原型上定义了一系列方法。其中,getRandomThings方法用于根据type参数获取随机的left值、top值、向下的速度、向右的速度或雪花的大小。init方法用于初始化雪花,设置容器的宽度和高度,并创建指定数量的雪花元素,并将其添加到容器中。start方法用于控制雪花的下落,通过定时器和闭包实现分批下落的效果。doStart方法用于针对每个雪花设置定时处理,根据当前位置和速度计算新的位置,并更新雪花元素的样式值,使其动起来。getStyle方法用于获取元素的样式值。

最后,在全局作用域中创建了一个Snow对象,传入了300个雪花和每批下落的雪花数量为30,从而开始执行下雪效果。

三、运行效果

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

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

相关文章

微服务学习Day3

文章目录 初始DockerDocker介绍Docker与虚拟机镜像和容器 Docker的基本操作镜像操作容器命令数据卷挂载数据卷 Dockerfile自定义镜像Docker-Compose介绍Docker-Compose部署微服务镜像仓库 初始Docker Docker介绍 Docker与虚拟机 镜像和容器 Docker的基本操作 镜像操作 容器命…

Pandas Series Mastery: 从基础到高级应用的完整指南【第83篇—Series Mastery】

Pandas Series Mastery: 从基础到高级应用的完整指南 Pandas是Python中一流的数据处理库&#xff0c;它为数据科学家和分析师提供了强大的工具&#xff0c;简化了数据清理、分析和可视化的流程。在Pandas中&#xff0c;Series对象是最基本的数据结构之一&#xff0c;它为我们处…

MATLAB知识点:datasample函数(★★☆☆☆)随机抽样的函数,能对矩阵数据进行随机抽样

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 节选自第3章&#xff1a;课后习题讲解中拓展的函数 在讲解第三…

Ubuntu Desktop 显示文件路径

Ubuntu Desktop 显示文件路径 1. GUI hot key2. CLIReferences 1. GUI hot key Ctrl L: 显示文件路径 2. CLI right click -> Open in Terminal -> pwd strongforeverstrong:~/Desktop$ pwd /home/strong/DesktopReferences [1] Yongqiang Cheng, https://yongqiang…

Leetcode1686. 石子游戏 VI

Every day a Leetcode 题目来源&#xff1a;1686. 石子游戏 VI 解法1&#xff1a;贪心 排序 贪心的思想&#xff1a; 这道题模拟一个石子游戏&#xff0c;求解最后的比赛结果。 题目说两位玩家都会采用 最优策略 进行游戏&#xff0c;那么关键点就在于什么是最优策略&…

docker (五)-docker存储-数据持久化

将数据存储在容器中&#xff0c;一旦容器被删除&#xff0c;数据也会被删除。同时也会使容器变得越来越大&#xff0c;不方便恢复和迁移。 将数据存储到容器之外&#xff0c;这样删除容器也不会丢失数据。一旦容器故障&#xff0c;我们可以重新创建一个容器&#xff0c;将数据挂…

Swift Combine 合并多个管道以更新 UI 元素 从入门到精通十七

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

Qt:Qt3个窗口类的区别、VS与QT项目转换

一、Qt3个窗口类的区别 QMainWindow&#xff1a;包含菜单栏、工具栏、状态栏 QWidget&#xff1a;普通的一个窗口&#xff0c;什么也不包括 QDialog&#xff1a;对话框&#xff0c;常用来做登录窗口、弹出窗口&#xff08;例如设置页面&#xff09; QDialog实现简易登录界面…

【c++】list 模拟

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能手撕list模拟 > 毒鸡汤&#xff1a;不为模糊…

html从零开始8:css3新特性、动画、媒体查询、雪碧图、字体图标【搬代码】

css3新特性 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, …

vue导出word文档(图文示例)

第076个 查看专栏目录: VUE 本文章目录 示例说明示例效果图导出的文件效果截图示例源代码参数说明&#xff1a;重要提示&#xff1a;API 参考网址 示例说明 在Vue中导出Word文档&#xff0c;可以使用第三方库file-saver和html-docx-js。首先需要安装这两个库&#xff1a; npm …

Java微服务学习Day2

文章目录 Nacos配置管理统一配置管理配置热更新![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c8a2d17baeef411980b44b432eb9692a.png)配置共享搭建Nacos集群 Feign远程调用介绍自定义配置性能优化最佳实践 Gateway服务网关介绍搭建网关服务路由断言工厂路由过滤器…

Python hash函数

在Python编程中&#xff0c;hash()函数是一个重要的内置函数&#xff0c;用于计算对象的哈希值。哈希值是一种由固定长度的字符串表示的数据摘要&#xff0c;通常用于在散列表中快速查找、比较对象或数据完整性验证等场景。本文将深入探讨Python中的hash()函数&#xff0c;包括…

【Linux网络编程五】Tcp套接字编程(四个版本服务器编写)

【Linux网络编程五】Tcp套接字编程(四个版本服务器编写&#xff09; [Tcp套接字编程]一.服务器端进程&#xff1a;1.创建套接字2.绑定网络信息3.设置监听状态4.获取新连接5.根据新连接进行通信 二.客户端进程&#xff1a;1.创建套接字2.连接服务器套接字3.连接成功后进行通信 三…

2.15练习

选择题 1. B2. B3. C4. D5. A6. B7. C8. B9. D10. B11. A12. B 填空题 1. a b c 2.string s: I like it. String t:A like it. 3. 30 10 30 n Learning

云计算基础-虚拟机迁移原理

什么是虚拟机迁移 虚拟机迁移是指将正在运行的虚拟机实例从一个物理服务器&#xff08;或主机&#xff09;迁移到另一个物理服务器&#xff08;或主机&#xff09;的过程&#xff0c;而不会中断虚拟机的运行。 虚拟机拟机迁移分类虚 热迁移&#xff1a;开机状态下迁移 冷迁…

“分布式透明化”在杭州银行核心系统上线之思考

导读 随着金融行业数字化转型的需求&#xff0c;银行核心系统的升级改造成为重要议题。杭州银行成功上线以 TiDB 为底层数据库的新一代核心业务系统&#xff0c;该实践采用应用与基础设施解耦、分布式透明化的设计开发理念&#xff0c;推动银行核心系统的整体升级。 本文聚焦…

H12-821_44

44.如图所示的网络,R1设备配置路由渗透,那么R1设备把Level-2的LSP发送给R3,使R3可以获知全网路由。 A.正确 B.错误 答案&#xff1a;B 注释&#xff1a; 感觉题目描述有两个问题&#xff1a; 1. R3是Level-1-2路由器&#xff0c;本来就可以学习到Level-2的路由。题目中的R3应该…

第七篇【传奇开心果系列】Python微项目技术点案例示例:数据可视化界面图形化经典案例

传奇开心果微博系列 系列微博目录Python微项目技术点案例示例系列 微博目录一、微项目开发背景和项目目标&#xff1a;二、雏形示例代码三、扩展思路介绍四、数据输入示例代码五、数据分析示例代码六、排名统计示例代码七、数据导入导出示例代码八、主题定制示例代码九、数据过…

微信网页版能够使用(会顶掉微信app的登陆)

一、文件结构 新建目录chrome新建icons&#xff0c;其中图片你自己找吧新建文件manifest.json新建文件wx-rules.json 二、文件内容 对应的png你们自己改下 1、manifest.json {"manifest_version": 3,"name": "wechat-need-web","author…