2025新春烟花代码(二)HTML5实现孔明灯和烟花效果

news2025/1/10 18:04:21

效果展示

在这里插入图片描述

源代码

<!DOCTYPE html>
<html lang="en">
<script>
  var _hmt = _hmt || [];
  (function () {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?45f95f1bfde85c7777c3d1157e8c2d34";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
  })();
</script>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>炸弹爆炸和烟花效果</title>
  <style>
    /* 夜空背景 */
    body, html {
      margin: 0;
      padding: 0;
      overflow: hidden;
      background: #000;
    }

    /* 星空背景 */
    .starry-background {
      position: absolute;
      width: 100%;
      height: 100%;
      background: radial-gradient(circle at bottom, #001025, #000000);
      z-index: -1;
    }

    .stars {
      position: absolute;
      width: 100%;
      height: 100%;
      background: url('https://i.imgur.com/3Zv2v1m.png') repeat;
      opacity: 0.5;
      animation: twinkle 5s infinite alternate;
    }

    @keyframes twinkle {
      from {
        opacity: 0.3;
      }
      to {
        opacity: 0.7;
      }
    }

    /* 孔明灯样式 */
    .lantern {
      position: absolute;
      width: 30px;
      height: 45px;
      background: radial-gradient(circle, #ff8c00, #ff4500);
      border-radius: 10px;
      box-shadow: 0 0 10px rgba(255, 140, 0, 0.8);
      animation: floatUp infinite linear;
    }

    @keyframes floatUp {
      0% {
        transform: translateY(100vh); /* 从页面底部开始 */
        opacity: 0;
      }
      10% {
        opacity: 1;
      }
      100% {
        transform: translateY(-200%); /* 上升到页面外 */
        opacity: 0;
      }
    }

    /* 新春快乐文本样式 */
    .new-year-text {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-family: 'Arial', sans-serif;
      font-size: 100px; /* 增大字体 */
      font-weight: bold;
      color: #ff8c00;
      text-shadow: 2px 2px 10px rgba(255, 140, 0, 0.8);
      opacity: 0; /* 初始透明 */
      transition: opacity 3s ease-out; /* 设置渐变效果 */
    }
  </style>
</head>
<body>
  <!-- 星空背景 -->
  <div class="starry-background">
    <div class="stars"></div>
  </div>

  <!-- 新春快乐文本 -->
  <div class="new-year-text">2025 新春快乐!</div>

  <!-- 孔明灯容器 -->
  <div class="lantern-container"></div>

  <!-- 烟花效果画布 -->
  <canvas id="fireworks"></canvas>

  <script>
    // 初始化孔明灯
    const lanternContainer = document.querySelector('.lantern-container');
    
    // 创建一个生成孔明灯的函数,逐渐增加
    let lanternCount = 0;
    function generateLantern() {
      const lantern = document.createElement('div');
      lantern.classList.add('lantern');
      lantern.style.left = Math.random() * 100 + '%';
      lantern.style.animationDuration = `${10 + Math.random() * 5}s`;
      lanternContainer.appendChild(lantern);
      lanternCount++;
      if (lanternCount >= 50) clearInterval(lanternInterval);  // 限制最大数量
    }

    // 设置一个间隔,逐渐添加孔明灯
    const lanternInterval = setInterval(generateLantern, 200);  // 每200ms增加一个孔明灯

    // 烟花效果
    const canvas = document.getElementById('fireworks');
    const ctx = canvas.getContext('2d');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    let particles = [];
    function createFirework(x, y) {
      const particleCount = 150;
      for (let i = 0; i < particleCount; i++) {
        particles.push(new Particle(x, y));
      }
    }

    class Particle {
      constructor(x, y) {
        this.x = x;
        this.y = y;
        this.size = Math.random() * 3 + 1;
        this.speedX = Math.random() * 6 - 3;
        this.speedY = Math.random() * 6 - 3;
        this.color = `hsl(${Math.random() * 360}, 100%, 50%)`;
        this.alpha = 1;
      }

      update() {
        this.x += this.speedX;
        this.y += this.speedY;
        this.alpha -= 0.01;
      }

      draw() {
        ctx.globalAlpha = this.alpha;
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.fill();
      }
    }

    function animate() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      particles = particles.filter(particle => particle.alpha > 0);
      particles.forEach(particle => {
        particle.update();
        particle.draw();
      });
      requestAnimationFrame(animate);
    }

    function autoFireworks() {
      setInterval(() => {
        const x = Math.random() * canvas.width;
        const y = Math.random() * canvas.height / 2;
        createFirework(x, y);
      }, 300);
    }

    animate();
    autoFireworks();

    // 绘制炸弹函数(没有导火线)
    let bombScale = 1; // 炸弹的初始大小
    let bombY = window.innerHeight / 2; // 将炸弹固定在屏幕中间
    let bombX = window.innerWidth / 2;
    let bombTimer = 0;
    let isExploding = false; // 是否处于爆炸状态
    let bombActive = true; // 判断炸弹是否仍然存在

    function drawBomb(x, y, scale) {
      ctx.save();
      ctx.beginPath();
      ctx.arc(x, y, 30 * scale, 0, Math.PI * 2, false); // 绘制炸弹的圆形,随着scale变化
      ctx.fillStyle = '#ffcc00'; // 黄色
      ctx.fill();
      ctx.shadowBlur = 15;
      ctx.shadowColor = 'rgba(255, 204, 0, 0.8)'; // 添加阴影
      ctx.lineWidth = 4;
      ctx.strokeStyle = '#ff9900';
      ctx.stroke();
      ctx.restore();
    }

    // 动画函数:炸弹上升到中间并开始呼吸效果
    function animateBomb() {
      if (bombActive) {
        // 在前200帧,炸弹开始呼吸效果(大小不断变化)
        if (bombTimer < 200) {
          bombScale = 1 + Math.sin(bombTimer / 30) * 0.2; // 使炸弹有呼吸的效果
        } else if (bombTimer >= 200 && !isExploding) {
          // 经过一段时间后,炸弹开始爆炸
          isExploding = true;
          setTimeout(() => {
            document.querySelector('.new-year-text').style.opacity = 1;  // 显示文本
            createFirework(bombX, bombY); // 同时创建烟花
            bombActive = false; // 爆炸后隐藏炸弹
          }, 500); // 延迟0.5秒后爆炸
        }

        drawBomb(bombX, bombY, bombScale);
      }

      bombTimer++;
      requestAnimationFrame(animateBomb); // 循环调用动画
    }

    // 页面加载5秒后才开始炸弹动画
    setTimeout(animateBomb, 5000); // 5秒后开始炸弹动画
  </script>
</body>
</html>

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

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

相关文章

同步整流 MT6705 应用注意事项

MT6705 是用于反激式变换器的高性能45V 同步整流器。它兼容各种反激转换器类型。支持 DCM、CCM 和准谐振模式。MT6705集成了一个40V功率MOSFET&#xff0c;可以取代肖特基二极管&#xff0c;提高效率。MT6705 PCB 布局应遵循以下规则: 1、VCC 电容器: VCC 引脚必须放置电容,电容…

LLaMA-Factory web微调大模型并导出大模型

LLaMA-Factory 开源大模型如LLaMA&#xff0c;Qwen&#xff0c;Baichuan等主要都是使用通用数据进行训练而来&#xff0c;其对于不同下游的使用场景和垂直领域的效果有待进一步提升&#xff0c;衍生出了微调训练相关的需求&#xff0c;包含预训练&#xff08;pt&#xff09;&am…

Jenkins内修改allure报告名称

背景&#xff1a; 最近使用Jenkins搭建自动化测试环境时&#xff0c;使用Jenkins的allure插件生成的报告&#xff0c;一直显示默认ALLURE REPORT&#xff0c;想自定义成与项目关联的名称&#xff0c;如图所示&#xff0c;很明显自定义名称显得高大上些&#xff0c;之前…

RK3588平台开发系列讲解(系统篇)Linux Kconfig的语法

文章目录 一、什么是Kconfig二、config模块三、menuconfig四、menu 和 endmenu五、choice 和 endchoice六、source七、depends on八、default九、help十、逻辑表达式沉淀、分享、成长,让自己和他人都能有所收获!😄 一、什么是Kconfig Kconfig的语法及代码结构非常简单。本博…

Android原生开发同一局域网内利用socket通信进行数据传输

1、数据接收端代码如下&#xff0c;注意&#xff1a;socket 接收信息需要异步运行&#xff1a; // port 端口号自定义一个值&#xff0c;比如 8888&#xff0c;但需和发送端使用的端口号保持一致 ServerSocket serverSocket new ServerSocket(port); while (true) {//这里为了…

Elasticsearch学习(1) : 简介、索引库操作、文档操作、RestAPI、RestClient操作

目录 1.elasticsearch简介1.1.了解es1.2.倒排索引正向索引和倒排索引 1.3.es的一些概念:文档和字段&#xff1b;索引和映射&#xff1b;Mysql与ES1.4.安装es、kibana部署单点es部署kibanaIK分词器安装IK分词器与测试扩展与停用词词典总结 部署es集群 2.索引库操作2.1.mapping映…

Clickhouse基础(一)

操作命令&#xff1a; sudo clickhouse start sudo clickhouse restart sudo clickhouse status进入clickhouse clickhouse-client -mCREATE TABLE db_13.t_assist (modelId UInt64,taskId UInt64,testNo String,tdId UInt64,eventDay String,eventDaytime UInt64,eventBatch …

记录将springboot的jar包和lib分离,使用docker-compose部署

本文讲诉如何把jar里的lib依赖包独立出来&#xff0c;方便更新服务时&#xff0c;缩小jar的体积&#xff0c;下面以若依的system服务为例&#xff0c;配置中的路径请酌情修改&#xff0c;主要提供大致配置逻辑 第一步&#xff1a;修改项目的pom.xml&#xff0c;调整build的配…

【对象存储】-- s3:\\、s3n:\\、s3a:\\ 简介

目录 1. s3:\ 2. s3n:\ 3. s3a:\ 区别对比 总结 在 Hadoop 和大数据处理领域&#xff0c;s3:\\、s3n:\\ 和 s3a:\\ 是访问 Amazon S3 的不同文件系统实现方式。以下是它们的简要介绍、区别及应用场景&#xff1a; 1. s3:\ 全称&#xff1a;Hadoop S3 Native FileSystem。…

Springboot3.x工程创建及必要引用(基础篇)

下面从环境的安装和配置开始&#xff0c;到Springboot3.x工程创建&#xff0c;记录一下让完全没有基础的小白用户也能够开始自己的第一个项目。 准备 安装JDK环境&#xff08;这里最好安装JDK17及以上版本&#xff09;安装IntelliJ IDEA Ultimate工具&#xff08;可以从官网下…

腾讯云AI代码助手-公司职位分析AI助手

作品简介 腾讯云AI代码助手是一款智能工具&#xff0c;专注于为公司提供职位分析服务。通过自然语言处理和机器学习技术&#xff0c;它能快速解析职位描述&#xff0c;提取关键信息&#xff0c;并提供数据驱动的洞察&#xff0c;帮助公司优化招聘流程和职位设计。 技术架构 …

QML学习(八) Quick中的基础组件:Item,Rectangle,MouseArea说明及使用场景和使用方法

上一篇中我们从设计器里可以看到Qt Quick-Base中有几大基础组件&#xff0c;如下图&#xff0c;这篇文章先介绍下Item&#xff0c;Rectangle&#xff0c;MouseArea这三个的说明及使用场景和使用方法 Item Item 是 QML 中所有可视元素的基类&#xff0c;是一个非常基础和通用的…

宇航用VIRTEX5系列FPGA的动态刷新方法及实现

SRAM型FPGA在宇航领域有广泛的应用&#xff0c;为解决FPGA在空间环境中的单粒子翻转问题&#xff0c;增强设计的可靠性&#xff0c;本文介绍一种低成本的抗辐照解决方案。该方案从外置高可靠存储器中读取配置数据&#xff0c;通过定时刷新结合三模冗余的方式消除单粒子影响&…

03.MPLS静态LSP配置实验

MPLS静态LSP配置实验 1、实验环境2、基础配置开启全局mpls接口下开启mpls配置静态LSP配置FEC从1.1.1.1到3.3.3.3配置FEC从3.3.3.3到1.1.1.13、信息查看查看LFIB表(标签转发信息表)查看FIB表(转发信息表)查看详细FFIB表tracert lsp iptracert -vping lsp ip4、抓包验证1、实…

el-table表格合并某一列

需求&#xff1a;按照下图完成单元格合并&#xff0c;数据展示 可以看到科室列是需要合并的 并加背景色展示&#xff1b;具体代码如下&#xff1a; <el-tableref"tableA":data"tableDataList":header-cell-style"{ backgroundColor: #f2dcdb, col…

PostgreSQL学习笔记(二):PostgreSQL基本操作

PostgreSQL 是一个功能强大的开源关系型数据库管理系统 (RDBMS)&#xff0c;支持标准的 SQL 语法&#xff0c;并扩展了许多功能强大的操作语法. 数据类型 数值类型 数据类型描述存储大小示例值SMALLINT小范围整数&#xff0c;范围&#xff1a;-32,768 到 32,7672 字节-123INTE…

javaEE-网络编程4.TCP回显服务器

目录 TCP流套接字编程 一.API介绍 ServerSocket类 构造方法&#xff1a; ​编辑方法&#xff1a; Socket类 构造方法&#xff1a; 方法&#xff1a; 二、TCP连接 三、通过TCP实现回显服务器 TCP服务端&#xff1a; 1.创建Socket对象 2.构造方法 3.start方法 TCP客…

RIS智能无线电反射面:原理、应用与MATLAB代码示例

一、引言 随着无线通信技术的快速发展,人们对通信系统的容量、覆盖范围、能效以及安全性等方面的要求日益提高。传统的无线通信系统主要通过增加基站数量、提高发射功率和优化天线阵列等方式来提升性能,但这些方法面临着资源有限、能耗高和成本上升等挑战。因此,探索新的无线…

合并模型带来的更好性能

研究背景与问题提出 在人工智能领域&#xff0c;当需要处理多个不同任务时&#xff0c;有多种方式来运用模型资源。其中&#xff0c;合并多个微调模型是一种成本效益相对较高的做法&#xff0c;相较于托管多个专门针对不同任务设计的模型&#xff0c;能节省一定成本。然而&…

城市生命线安全综合监管平台

【落地产品&#xff0c;有需要可留言联系&#xff0c;支持项目合作或源码合作】 一、建设背景 以关于城市安全的重要论述为建设纲要&#xff0c;聚焦城市安全重点领域&#xff0c;围绕燃气爆炸、城市内涝、地下管线交互风险、第三方施工破坏、供水爆管、桥梁坍塌、道路塌陷七…