爱心气泡表白代码-HTML【附源码】

简介: 每戳破一颗爱心气泡,都会有一句专属于你的情话悄然绽放~愿天下有情人终成眷属

一:效果展示

P51emFS8_converted.gif

二:核心动画

(1)交互功能:

  • 爱心被点击后触发爆炸并生成情话文字

(2)爱心气泡动画:

  • 在随机位置生成多种颜色多种样式不同大小(32px~64px)的爱心
  • 爱心从屏幕底部缓慢上升到顶部,同时旋转360度并逐渐透明
  • 限制屏幕内最大爱心数量为30,避免卡顿

(3)随机情话文字:

  • 点击爱心时在爆炸位置显示情话
  • 从预设的文案中随机选择生成(如:我爱你;遇见你真好....等)
  • 随机颜色和字体大小(16px~22px)增强视觉层次

(4)背景特效:

  • 使用linear-gradient创建粉色系渐变天空(#ff9a9e → #fad0c4)
  • 通过JavaScript动态生成30个随机位置、大小、颜色的圆形星星(div.star)
  • 应用twinkle动画让星星闪烁(缩放+透明度变化)

三:完整代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>多彩爱心气泡上升动画</title>
    <style>
        body {
    
            margin: 0;
            padding: 0;
            overflow: hidden;
            height: 100vh;
            background: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
        }

        .floating-heart {
    
            position: fixed;
            font-size: 24px;
            z-index: 1000;
            pointer-events: auto; 
            cursor: default; 
            transform: translateY(100vh) rotate(0deg);
            opacity: 0;
            animation: floatHeart linear forwards;
            will-change: transform, opacity;
            transition: transform 0.2s ease, opacity 0.2s ease; 
        }

        @keyframes floatHeart {
    
            0% {
    
                transform: translateY(100vh) rotate(0deg);
                opacity: 1;
            }
            100% {
    
                transform: translateY(-100px) rotate(360deg);
                opacity: 0;
            }
        }

        @keyframes burstHeart {
    
            0% {
    
                transform: translate(-50%, -50%) scale(1) rotate(0deg);
                opacity: 1;
            }
            30% {
    
                transform: translate(-50%, -50%) scale(1.8) rotate(180deg);
                opacity: 0.9;
            }
            100% {
    
                transform: translate(-50%, -50%) scale(0) rotate(360deg);
                opacity: 0;
            }
        }

        .love-text {
    
            position: fixed;
            font-size: 18px;
            color: #fff;
            font-family: "Microsoft Yahei", sans-serif;
            text-shadow: 0 0 5px rgba(0,0,0,0.3);
            z-index: 1001;
            pointer-events: none;
            opacity: 0;
            animation: loveTextFade 1s ease forwards;
            transform: translate(-50%, -50%); 
        }

        @keyframes loveTextFade {
    
            0% {
    
                transform: translate(-50%, -50%) scale(0);
                opacity: 1;
            }
            50% {
    
                transform: translate(-50%, -50%) scale(1.2);
                opacity: 1;
            }
            100% {
    
                transform: translate(-50%, -50%) scale(0);
                opacity: 0;
            }
        }
        .star {
    
            position: absolute;
            background-color: #fff;
            border-radius: 50%;
            z-index: 1;
            animation: twinkle infinite;
        }

        @keyframes twinkle {
    
            0%, 100% {
     opacity: 0.3; transform: scale(0.8); }
            50% {
     opacity: 1; transform: scale(1.2); }
        }
    </style>
</head>
<body>
    <div class="bg-animation" id="bgAnimation"></div>

    <script>
        const config = {
    
            bgStarCount: 30,
            maxHeartsOnScreen: 30,
            heartSizeRange: [32, 64],
            animationDurationRange: [8, 15],
            spawnInterval: 500,
            heartSymbols: ['❤️', '💖', '💘', '💝', '💓', '💗', '💕', '💙', '💛', '💜', '💚'],
            heartColors: [
                '#ff69b4', '#ff1493', '#ff4500', '#ffd700', '#ff8c00',
                '#ff6347', '#dc143c', '#c71585', '#ff00ff', '#9370db',
                '#00bfff', '#00fa9a', '#ff7f50', '#ff6eb4', '#ff91a4'
            ],
            loveTexts: [
    "我爱你", "喜欢你", "心动了", "遇见你真好", "满心欢喜",
    "余生都是你", "满眼都是你", "超喜欢你", "你最珍贵", "甜蜜暴击",
    "心有灵犀", "双向奔赴", "温柔以待", "人间理想", "甜度超标",
    "星河万顷都是你", "万物不及你", "为你心动", "浪漫不渝", "岁岁年年",
    "你是我的例外与偏爱", "想和你共度每一个晨昏", "你的笑容是我每日的阳光",
    "遇见你,是我这辈子最美的意外", "我的世界因你而完整", "你是我所有的少女心和英雄梦",
    "想牵你的手,从心动到古稀", "你是我平淡岁月里的心之所向", "我贪恋的人间烟火,不偏不倚全是你",
    "你是我疲惫生活中的温柔梦想", "想和你一起浪费时光,直到时光的尽头", "我的宇宙里,你是最亮的星",
    "你是我漫漫余生里斩钉截铁的梦想", "想和你一起看遍世间风景,然后只与你细水长流",
    "你是我疲惫生活中的唯一解药", "我的喜欢写在风里,从此整个世界都是你",
    "你是我所有温柔与浪漫的源头", "想和你一起虚度短的沉默,长的无意义,一起消磨精致而苍老的宇宙",
    "你是我灵魂的归宿,是我一生的守候", "我的爱意汹涌,看世间万物都浪漫心动",
    "你是我平淡岁月里的星辰大海", "想和你一起走过四季,看遍人间烟火",
    "你是我所有美好与幸运的起点", "我的世界很小,小到只能装下你一个人",
    "你是我疲惫生活中的不期而遇", "想和你一起慢慢变老,直到哪里也去不了"
]

        };

        let activeHearts = 0;
        let allHearts = [];

        function createBackgroundStars() {
    
            const bgAnimation = document.getElementById('bgAnimation');

            for (let i = 0; i < config.bgStarCount; i++) {
    
                const star = document.createElement('div');
                star.className = 'star';
                const size = Math.random() * 3 + 1;
                star.style.width = `${
      size}px`;
                star.style.height = `${
      size}px`;
                star.style.left = `${
      Math.random() * 100}%`;
                star.style.top = `${
      Math.random() * 100}%`;
                star.style.animationDuration = `${
      Math.random() * 3 + 2}s`;
                star.style.animationDelay = `${
      Math.random() * 5}s`;
                star.style.backgroundColor = `hsl(${
      Math.random() * 360}, 80%, 80%)`;

                bgAnimation.appendChild(star);
            }
        }

        function createLoveText(x, y) {
    
            const text = document.createElement('div');
            text.className = 'love-text';
            const randomText = config.loveTexts[Math.floor(Math.random() * config.loveTexts.length)];
            text.innerText = randomText;
            text.style.left = `${
      x}px`;
            text.style.top = `${
      y}px`;
            const randomColor = config.heartColors[Math.floor(Math.random() * config.heartColors.length)];
            text.style.color = randomColor;
            const fontSize = Math.random() * 6 + 16;
            text.style.fontSize = `${
      fontSize}px`;
            document.body.appendChild(text);

            setTimeout(() => {
    
                if (text.parentNode) {
    
                    text.parentNode.removeChild(text);
                }
            }, 1000);
        }

        function handleHeartClick(e) {
    
            const heart = e.target;
            const rect = heart.getBoundingClientRect();
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;
            heart.style.animation = 'none';
            heart.style.transition = 'none';
            heart.style.left = `${
      centerX}px`;
            heart.style.top = `${
      centerY}px`;
            heart.style.transform = 'translate(-50%, -50%)';
            heart.style.animation = 'burstHeart 0.5s ease forwards';
            createLoveText(centerX, centerY);

            setTimeout(() => {
    
                if (heart.parentNode) {
    
                    heart.parentNode.removeChild(heart);
                }
                activeHearts = Math.max(0, activeHearts - 1);
                allHearts = allHearts.filter(h => h !== heart);
            }, 500);
        }

        function createHeart() {
    
            if (activeHearts >= config.maxHeartsOnScreen) return;
            activeHearts++;
            const heart = document.createElement('div');
            heart.className = 'floating-heart';
            const randomSymbol = config.heartSymbols[Math.floor(Math.random() * config.heartSymbols.length)];
            heart.innerHTML = randomSymbol;
            const randomColor = config.heartColors[Math.floor(Math.random() * config.heartColors.length)];
            heart.style.color = randomColor;
            const leftPos = Math.random() * (window.innerWidth - 60) + 30;
            heart.style.left = `${
      leftPos}px`;
            const size = Math.random() * (config.heartSizeRange[1] - config.heartSizeRange[0]) + config.heartSizeRange[0];
            heart.style.fontSize = `${
      size}px`;
            const duration = Math.random() * (config.animationDurationRange[1] - config.animationDurationRange[0]) + config.animationDurationRange[0];
            heart.style.animationDuration = `${
      duration}s`;
            const rotationDirection = Math.random() > 0.5 ? 1 : -1;
            heart.style.setProperty('--rotation', `${
      360 * rotationDirection}deg`);
            heart.addEventListener('click', handleHeartClick);
            document.body.appendChild(heart);
            allHearts.push(heart);

            heart.addEventListener('animationend', function(e) {
    
                if (e.animationName === 'floatHeart') {
    
                    if (heart.parentNode) {
    
                        heart.parentNode.removeChild(heart);
                    }
                    activeHearts = Math.max(0, activeHearts - 1);
                    allHearts = allHearts.filter(h => h !== heart);
                }
            });
        }

        function startHeartSpawner() {
    
            for (let i = 0; i < config.maxHeartsOnScreen / 2; i++) {
    
                setTimeout(createHeart, i * config.spawnInterval / 2);
            }

            setInterval(createHeart, config.spawnInterval);
        }

        window.addEventListener('resize', () => {
    
            allHearts.forEach(heart => {
    
                if (heart.parentNode) {
    
                    heart.parentNode.removeChild(heart);
                }
            });

            activeHearts = 0;
            allHearts = [];
            startHeartSpawner();
        });

        window.addEventListener('load', () => {
    
            createBackgroundStars();
            startHeartSpawner();
        });
    </script>
</body>
</html>

四:代码分析

(1)爱心动画模块

        /* 浮动爱心基础样式 */
        .floating-heart {
   
            position: fixed;
            font-size: 24px;
            z-index: 1000;
            pointer-events: auto; /* 允许点击事件 */
            cursor: default; 
            transform: translateY(100vh) rotate(0deg); /* 初始位置在底部 */
            opacity: 0;
            animation: floatHeart linear forwards; /* 应用上升动画 */
            will-change: transform, opacity; /* 优化动画性能 */
            transition: transform 0.2s ease, opacity 0.2s ease; /* 平滑过渡效果 */
        }

        /* 爱心上升动画 */
        @keyframes floatHeart {
   
            0% {
   
                transform: translateY(100vh) rotate(0deg); /* 从底部开始 */
                opacity: 1;
            }
            100% {
   
                transform: translateY(-100px) rotate(360deg); /* 上升到顶部并旋转一圈 */
                opacity: 0; /* 逐渐消失 */
            }
        }

        /* 爱心点击爆炸动画 */
        @keyframes burstHeart {
   
            0% {
   
                transform: translate(-50%, -50%) scale(1) rotate(0deg);
                opacity: 1;
            }
            30% {
   
                transform: translate(-50%, -50%) scale(1.8) rotate(180deg); /* 放大并旋转 */
                opacity: 0.9;
            }
            100% {
   
                transform: translate(-50%, -50%) scale(0) rotate(360deg); /* 缩小消失 */
                opacity: 0;
            }
        }

        /* 爱心文字样式 */
        .love-text {
   
            position: fixed;
            font-size: 18px;
            color: #fff;
            font-family: "Microsoft Yahei", sans-serif;
            text-shadow: 0 0 5px rgba(0,0,0,0.3); /* 文字阴影 */
            z-index: 1001;
            pointer-events: none; /* 禁止点击事件 */
            opacity: 0;
            animation: loveTextFade 1s ease forwards; /* 淡入淡出动画 */
            transform: translate(-50%, -50%); /* 居中定位 */
        }

        /* 文字淡入淡出动画 */
        @keyframes loveTextFade {
   
            0% {
   
                transform: translate(-50%, -50%) scale(0); /* 从缩小开始 */
                opacity: 1;
            }
            50% {
   
                transform: translate(-50%, -50%) scale(1.2); /* 放大效果 */
                opacity: 1;
            }
            100% {
   
                transform: translate(-50%, -50%) scale(0); /* 缩小消失 */
                opacity: 0;
            }
        }

(2)配置对象

        // 配置对象,集中管理所有可配置参数
        const config = {
   
            bgStarCount: 30, // 背景星星数量
            maxHeartsOnScreen: 30, // 屏幕上最大爱心数量
            heartSizeRange: [32, 64], // 爱心大小范围(px)
            animationDurationRange: [8, 15], // 动画持续时间范围(s)
            spawnInterval: 500, // 爱心生成间隔(ms)
            heartSymbols: ['❤️', '💖', '💘', '💝', '💓', '💗', '💕', '💙', '💛', '💜', '💚'], // 爱心符号集合
            heartColors: [ // 爱心颜色集合
                '#ff69b4', '#ff1493', '#ff4500', '#ffd700', '#ff8c00',
                '#ff6347', '#dc143c', '#c71585', '#ff00ff', '#9370db',
                '#00bfff', '#00fa9a', '#ff7f50', '#ff6eb4', '#ff91a4'
            ],
            loveTexts: [ // 点击爱心后显示的文字集合
                "我爱你", "喜欢你", "心动了", "遇见你真好", "满心欢喜",
                "余生都是你", "满眼都是你", "超喜欢你", "你最珍贵", "甜蜜暴击",
                // 更多文字...
            ]
        };

        let activeHearts = 0; // 当前屏幕上活跃的爱心数量
        let allHearts = []; // 存储所有爱心元素的数组

(3)背景星星模块

        function createBackgroundStars() {
   
            const bgAnimation = document.getElementById('bgAnimation');
            for (let i = 0; i < config.bgStarCount; i++) {
   
                const star = document.createElement('div');
                star.className = 'star';
                const size = Math.random() * 3 + 1; // 随机大小(1-4px)
                star.style.width = `${
     size}px`;
                star.style.height = `${
     size}px`;
                star.style.left = `${
     Math.random() * 100}%`; // 随机水平位置
                star.style.top = `${
     Math.random() * 100}%`; // 随机垂直位置
                star.style.animationDuration = `${
     Math.random() * 3 + 2}s`; // 随机动画持续时间
                star.style.animationDelay = `${
     Math.random() * 5}s`; // 随机延迟
                star.style.backgroundColor = `hsl(${
     Math.random() * 360}, 80%, 80%)`; // 随机颜色
                bgAnimation.appendChild(star);
            }
        }

(4)爱心生成模块

        function createHeart() {
   
            if (activeHearts >= config.maxHeartsOnScreen) return; // 达到上限则不创建

            activeHearts++;
            const heart = document.createElement('div');
            heart.className = 'floating-heart';

            // 随机选择爱心符号和颜色
            const randomSymbol = config.heartSymbols[Math.floor(Math.random() * config.heartSymbols.length)];
            heart.innerHTML = randomSymbol;
            const randomColor = config.heartColors[Math.floor(Math.random() * config.heartColors.length)];
            heart.style.color = randomColor;

            // 随机位置和大小
            const leftPos = Math.random() * (window.innerWidth - 60) + 30;
            heart.style.left = `${
     leftPos}px`;
            const size = Math.random() * (config.heartSizeRange[1] - config.heartSizeRange[0]) + config.heartSizeRange[0];
            heart.style.fontSize = `${
     size}px`;

            // 随机动画持续时间
            const duration = Math.random() * (config.animationDurationRange[1] - config.animationDurationRange[0]) + config.animationDurationRange[0];
            heart.style.animationDuration = `${
     duration}s`;

            // 随机旋转方向
            const rotationDirection = Math.random() > 0.5 ? 1 : -1;
            heart.style.setProperty('--rotation', `${
     360 * rotationDirection}deg`);

            // 添加点击事件
            heart.addEventListener('click', handleHeartClick);
            document.body.appendChild(heart);
            allHearts.push(heart);

            // 动画结束后的处理
            heart.addEventListener('animationend', function(e) {
   
                if (e.animationName === 'floatHeart') {
   
                    if (heart.parentNode) {
   
                        heart.parentNode.removeChild(heart);
                    }
                    activeHearts = Math.max(0, activeHearts - 1);
                    allHearts = allHearts.filter(h => h !== heart);
                }
            });
        }

(5)文字显示模块

        function createLoveText(x, y) {
   
            const text = document.createElement('div');
            text.className = 'love-text';
            const randomText = config.loveTexts[Math.floor(Math.random() * config.loveTexts.length)];
            text.innerText = randomText;
            text.style.left = `${
     x}px`;
            text.style.top = `${
     y}px`;
            const randomColor = config.heartColors[Math.floor(Math.random() * config.heartColors.length)];
            text.style.color = randomColor;
            const fontSize = Math.random() * 6 + 16; // 随机字体大小(16-22px)
            text.style.fontSize = `${
     fontSize}px`;
            document.body.appendChild(text);

            // 1秒后自动移除文字元素
            setTimeout(() => {
   
                if (text.parentNode) {
   
                    text.parentNode.removeChild(text);
                }
            }, 1000);
        }

(6)点击交互模块

        function handleHeartClick(e) {
   
            const heart = e.target;
            const rect = heart.getBoundingClientRect();
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;

            // 重置样式为爆炸动画做准备
            heart.style.animation = 'none';
            heart.style.transition = 'none';
            heart.style.left = `${
     centerX}px`;
            heart.style.top = `${
     centerY}px`;
            heart.style.transform = 'translate(-50%, -50%)';
            heart.style.animation = 'burstHeart 0.5s ease forwards'; // 应用爆炸动画

            // 在爱心位置创建文字
            createLoveText(centerX, centerY);

            // 动画结束后移除爱心元素
            setTimeout(() => {
   
                if (heart.parentNode) {
   
                    heart.parentNode.removeChild(heart);
                }
                activeHearts = Math.max(0, activeHearts - 1);
                allHearts = allHearts.filter(h => h !== heart);
            }, 500);
        }
目录
相关文章
|
7月前
|
前端开发
前端开发 之 12个鼠标交互特效上【附完整源码】
本篇文章内容展示了彩色爱心滑动特效、粒子连结特效、彩色拖尾特效等炫酷的鼠标交互特效,并给出了完整的代码
628 8
|
6月前
|
JavaScript 前端开发 PHP
Laravel13 + Vue3 的免费可商用 PHP 管理后台 CatchAdmin V5.2.0 发布
CatchAdmin V5.2.0发布!基于Laravel 13 + Vue3的免费可商用后台系统,支持Token鉴权、RBAC权限、动态路由、代码生成、多云上传等,模块化设计,开箱即用,助力快速构建CMS/OA/CRM等企业级应用。(239字)
538 1
|
7月前
|
druid 安全 Java
网站后端连接数据库知识点大全(一)
教程来源:https://dnuhf.cn/article/162.html 本文系统梳理Web后端数据库连接核心知识:涵盖JDBC原理、主流驱动配置、PreparedStatement防注入、批处理;深入解析HikariCP、Druid、Tomcat JDBC三大连接池;详解Spring中数据源配置、JdbcTemplate及多数据源实践,助开发者构建高效、安全、稳定的数据库访问体系。
|
7月前
|
存储 NoSQL 安全
从单体到亿级流量:登录功能全场景设计指南,踩过的坑全给你填平了
本文系统剖析登录功能设计,按项目复杂度分四级:极简单体(Tomcat Session+BCrypt)、集群(Redis分布式会话+双令牌)、微服务(OAuth2.0统一认证中心)、高并发(多级缓存+智能风控)。强调设计须匹配业务规模,杜绝过度或缺失设计,并严守密码存储、传输、会话等八大安全红线。
618 1
|
监控 自动驾驶 数据可视化
GPS 人员定位系统:原理拆解 + 优劣分析 + 避坑指南(一)
本文详解GPS人员定位系统的工作原理,从卫星测距、三角定位到数据解算,解析其实现过程,并介绍实时定位、电子点名、轨迹回溯、智能考勤等核心功能,为后续优劣分析与避坑指南做铺垫。
|
7月前
|
存储 安全 算法
内存折叠术:Windows如何把有限的空间玩出花?
本文深入剖析Windows内存管理的底层魔术:从分页机制替代分段、虚拟地址映射与多级页表,到TLB加速、缺页中断处理、工作集与写时复制;涵盖大页优化、PFN数据库、ASLR/DEP安全机制,以及VirtualAlloc、内存映射文件等实战API,并延伸至内存压缩、NUMA架构与内核对象资源管理,全景展现操作系统如何以精妙算法驾驭物理限制。(239字)
1248 7
|
7月前
|
传感器 算法 前端开发
迷宫中的领航者:揭秘SLAM背后的数学逻辑
SLAM(同步定位与建图)是机器人实现空间感知的基石:在未知环境中,它 simultaneously 解决“我在哪”与“环境长什么样”这一鸡生蛋蛋生鸡的难题。本文系统解析其经典架构、数学本质(SE(3)、李代数)、前端里程计(特征/直接法)、后端优化(滤波→图优化)、闭环检测、多传感器融合、语义与神经表示等前沿演进,展现从几何建图到空间智能的恢弘跃迁。(239字)
1488 6
|
7月前
|
存储 Java 中间件
分布式协调双雄深度拆解:ZooKeeper 与 Nacos 从底层原理到生产实战全指南
本文深度解析ZooKeeper与Nacos两大分布式协调中间件:ZooKeeper专注强一致协调,基于ZAB协议与ZNode模型,适用于大数据生态;Nacos则提供AP/CP双模、三层数据隔离及长轮询机制,是云原生下配置中心+服务发现的一站式选择。二者核心能力、架构差异与选型建议全面对比,附生产实践与避坑指南。
1761 6
|
数据采集 文字识别 算法
精通RAG:从“能用”到“好用”的进阶优化与评估之道
你的RAG应用是否总是答非所问,或者检索到的内容质量不高?本文聚焦于RAG系统的进阶优化,深入探讨从查询转换、多路召回与重排序(Rerank)等高级检索策略,到知识库构建的最佳实践。更重要的是,我们将引入强大的`Ragas`评估框架,教你如何用数据驱动的方式,科学地量化和提升你的RAG系统性能。
1448 7
|
SQL Cloud Native API
NSDI'24 | 阿里云飞天洛神云网络论文解读——《Poseidon》揭秘新型超高性能云网络控制器
NSDI‘24于4月16-18日在美国加州圣塔克拉拉市举办,汇聚全球网络系统领域的专家。阿里云飞天洛神云网络的两篇论文入选,标志着其创新能力获广泛认可。其中,《Poseidon: A Consolidated Virtual Network Controller that Manages Millions of Tenants via Config Tree》介绍了波塞冬平台,该平台通过统一控制器架构、高性能配置计算引擎等技术,实现了对超大规模租户和设备的高效管理,显著提升了云网络性能与弹性。实验结果显示,波塞冬在启用EIP时的完成时间比Top 5厂商分别快1.8至55倍和2.6至4.8倍。
2124 145

热门文章

最新文章