HTML爱心流星雨

2024-08-31 10:52
文章标签 html frontend 爱心 流星雨

本文主要是介绍HTML爱心流星雨,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

写在前面

完整代码

代码分析

推荐系列

写在后面


在前面

如何用HTML代码实现爱心+流星雨的动态效果?本期博主将带着大家探索神奇的HTML。

完整代码

<!doctype html>
<html>
<head><meta charset="utf-8"><title>爱心流星雨</title><style>html,body {height: 100%;padding: 0;margin: 0;background-color: black;}canvas {position: absolute;width: 100%;height: 100%;}
</style>
</head>
<body><canvas id="pinkboard"></canvas><canvas id="stars"></canvas><script>var context;var arr = new Array();var starCount = 800;var rains = new Array();var rainCount = 20;//初始化画布及contextfunction init() {//获取canvasvar stars = document.getElementById("stars");windowWidth = window.innerWidth; //当前的窗口的高度stars.width = windowWidth;stars.height = window.innerHeight;//获取contextcontext = stars.getContext("2d");}//创建一个星星对象var Star = function () {this.x = windowWidth * Math.random();//横坐标this.y = 5000 * Math.random();//纵坐标this.text = "❤";//文本this.color = "#ea80b0";//颜色//产生随机颜色this.getColor = function () {var _r = Math.random();if (_r < 0.5) {this.color = "#333";} else {this.color = "#ea80b0";}}//初始化this.init = function () {this.getColor();}//绘制this.draw = function () {context.fillStyle = this.color;context.fillText(this.text, this.x, this.y);}}//页面加载的时候window.onload = function () {init();//画星星for (var i = 0; i < starCount; i++) {var star = new Star();star.init();star.draw();arr.push(star);}//画流星for (var i = 0; i < rainCount; i++) {var rain = new MeteorRain();rain.init();rain.draw();rains.push(rain);}playStars();//绘制闪动的星星playRains();//绘制流星}//星星闪起来function playStars() {for (var n = 0; n < starCount; n++) {arr[n].getColor();arr[n].draw();}setTimeout("playStars()", 100);}var MeteorRain = function () {this.x = -1;this.y = -1;this.length = -1;//长度this.angle = 30; //倾斜角度this.width = -1;//宽度this.height = -1;//高度this.speed = 1;//速度this.offset_x = -1;//横轴移动偏移量this.offset_y = -1;//纵轴移动偏移量this.alpha = 1; //透明度this.color1 = "#ea80b0";//流星的色彩this.color2 = "";  //流星的色彩this.init = function () //初始化
{this.getPos();this.alpha = 1;//透明度this.getRandomColor();//最小长度,最大长度var x = Math.random() * 80 + 150;this.length = Math.ceil(x);//                  x = Math.random()*10+30;this.angle = 30; //流星倾斜角x = Math.random() + 0.5;this.speed = Math.ceil(x); //流星的速度var cos = Math.cos(this.angle * 3.14 / 180);var sin = Math.sin(this.angle * 3.14 / 180);this.width = this.length * cos;  //流星所占宽度this.height = this.length * sin;//流星所占高度this.offset_x = this.speed * cos;this.offset_y = this.speed * sin;}this.getRandomColor = function () {var a = Math.ceil(255 - 240 * Math.random());//中段颜色this.color1 = "rgba(" + a + "," + a + "," + a + ",1)";//结束颜色this.color2 = "black";}this.countPos = function ()//
{//往左下移动,x减少,y增加this.x = this.x - this.offset_x;this.y = this.y + this.offset_y;}this.getPos = function () //
{//横坐标200--1200this.x = Math.random() * window.innerWidth; //窗口高度//纵坐标小于600this.y = Math.random() * window.innerHeight;  //窗口宽度}this.draw = function () //绘制一个流星的函数
{context.save();context.beginPath();context.lineWidth = 1; //宽度context.globalAlpha = this.alpha; //设置透明度//创建横向渐变颜色,起点坐标至终点坐标var line = context.createLinearGradient(this.x, this.y,this.x + this.width,this.y - this.height);//分段设置颜色line.addColorStop(0, "#ea80b0");line.addColorStop(0.3, this.color1);line.addColorStop(0.6, this.color2);context.strokeStyle = line;//起点context.moveTo(this.x, this.y);//终点context.lineTo(this.x + this.width, this.y - this.height);context.closePath();context.stroke();context.restore();}this.move = function () {//清空流星像素var x = this.x + this.width - this.offset_x;var y = this.y - this.height;context.clearRect(x - 3, y - 3, this.offset_x + 5, this.offset_y + 5);//                  context.strokeStyle="red";//                  context.strokeRect(x,y-1,this.offset_x+1,this.offset_y+1);//重新计算位置,往左下移动this.countPos();//透明度增加this.alpha -= 0.002;//重绘this.draw();}}//绘制流星function playRains() {for (var n = 0; n < rainCount; n++) {var rain = rains[n];rain.move();//移动if (rain.y > window.innerHeight) {//超出界限后重来context.clearRect(rain.x, rain.y - rain.height, rain.width, rain.height);rains[n] = new MeteorRain();rains[n].init();}}setTimeout("playRains()", 2);}var settings = {particles: {length: 500, duration: 2, velocity: 100, effect: -0.75, size: 20, },};(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) } }}());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;})();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;})();var ParticlePool = (function () {var particles,firstActive = 0,firstFree = 0,duration = settings.particles.duration;function ParticlePool(length) {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);firstFree++;if (firstFree == particles.length) firstFree = 0;if (firstActive == firstFree) firstActive++;if (firstActive == particles.length) firstActive = 0;};ParticlePool.prototype.update = function (deltaTime) {var i;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);}while (particles[firstActive].age >= duration && firstActive != firstFree) {firstActive++;if (firstActive == particles.length) firstActive = 0;}};ParticlePool.prototype.draw = function (context, image) {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, time;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;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;}context.beginPath();var t = -Math.PI;var point = to(t);context.moveTo(point.x, point.y);while (t < Math.PI) {t += 0.01;point = to(t);context.lineTo(point.x, point.y);}context.closePath();context.fillStyle = '#ea80b0';context.fill();var image = new Image();image.src = canvas.toDataURL();return image;})();function render() {requestAnimationFrame(render);var newTime = new Date().getTime() / 1000,deltaTime = newTime - (time || newTime);time = newTime;context.clearRect(0, 0, canvas.width, canvas.height);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);}particles.update(deltaTime);particles.draw(context, image);}function onResize() {canvas.width = canvas.clientWidth;canvas.height = canvas.clientHeight;}window.onresize = onResize;setTimeout(function () {onResize();render();}, 10);})(document.getElementById('pinkboard'));
</script>
</body>
</html>

代码分析

HTML和CSS

页面主要包含两个部分:一个<canvas>标签用于绘制粒子爱心效果,另一个<canvas>标签用于绘制闪烁的心形和流星动画。CSS设置了整个页面的背景颜色为黑色,并使两个画布覆盖整个浏览器窗口。

JavaScript

JavaScript部分主要通过window.onload事件来初始化画布和启动动画。init()函数设置了stars画布的宽度和高度,并获取其绘图上下文。

心形动画

心形动画由一个Star类实现,该类有以下属性和方法:

  • x:心形的横坐标。

  • y:心形的纵坐标。

  • text:显示的文本(心形符号)。

  • color:心形的颜色。

  • getColor():随机设置心形颜色。

  • init():初始化心形的颜色。

  • draw():在画布上绘制心形。

在页面加载时,会创建大量的Star对象,并调用其init()draw()方法进行绘制。playStars()函数使心形闪烁,通过不断调用getColor()draw()方法,并使用setTimeout定时器循环实现。

流星动画

流星动画由一个MeteorRain类实现,该类有以下属性和方法:

  • xy:流星的起始位置。

  • length:流星的长度。

  • angle:流星的倾斜角度。

  • widthheight:流星的宽高。

  • speed:流星的速度。

  • offset_xoffset_y:流星的横向和纵向位移量。

  • alpha:流星的透明度。

  • color1color2:流星的颜色(使用渐变效果)。

  • init():初始化流星的起始位置、速度和颜色。

  • getRandomColor():随机生成流星的颜色。

  • countPos():计算流星的位置。

  • getPos():生成流星的起始位置。

  • draw():在画布上绘制流星。

  • move():更新流星的位置。

在页面加载时,会创建一定数量的MeteorRain对象,并调用其init()draw()方法进行绘制。playRains()函数通过不断调用move()方法来更新流星的位置,并使用setTimeout定时器循环实现。

爱心动画

粒子爱心效果由多个类实现,包括PointParticleParticlePool。

  • Point类:表示二维平面上的一个点,提供克隆、长度和归一化方法。

  • Particle类:表示一个粒子,具有位置、速度、加速度和年龄等属性,提供初始化、更新和绘制方法。

  • ParticlePool类:管理粒子的池,提供添加、更新和绘制粒子的方法。

粒子爱心效果通过pointOnHeart(t)函数生成心形路径上的点。粒子池管理和更新这些粒子,并在每一帧动画中绘制它们。

在初始化时,会创建一个心形路径的粒子图像,并通过requestAnimationFrame实现动画的逐帧渲染。render()函数是动画的核心,负责更新时间、清空画布、创建新粒子、更新和绘制粒子。onResize()函数确保画布在窗口大小改变时自适应调整。

总结

整个代码通过HTML、CSS和JavaScript实现了一个视觉效果丰富的网页动画,展示了闪烁的心形和流星,以及中心的粒子爱心效果。通过使用canvas和逐帧动画技术,代码创造了一个生动的视觉体验。

推荐系列

序号目录
1HTML满屏跳动的爱心(可写字)
2HTML五彩缤纷的爱心
3HTML满屏漂浮爱心
4HTML情人节快乐
5HTML蓝色爱心射线
6HTML跳动的爱心(简易版)
7HTML粒子爱心
8HTML蓝色动态爱心
9HTML跳动的爱心(双心版)
10HTML橙色动态粒子爱心
11HTML旋转爱心
12HTML爱情树
13HTML3D相册
14HTML旋转相册
15HTML基础烟花秀
16HTML炫酷烟花秀
17HTML粉色烟花秀
18HTML新春烟花
19HTML龙年大吉
20HTML圣诞树
21HTML大雪纷飞
22HTML想见你
23HTML元素周期表
24HTML飞舞的花瓣
25HTML星空特效
26HTML黑客帝国字母雨
27HTML哆啦A梦
28HTML流星雨
29HTML沙漏爱心
30HTML爱心字母雨
31HTML爱心流星雨

写在后面

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

这篇关于HTML爱心流星雨的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1123698

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,