无需登录 数据私有 本地保存

粒子背景生成器 - 星空/气泡/雪花CSS效果

16
0
0
0
粒子设置
星空
🫧气泡
❄️雪花
🪲萤火虫
🌸樱花
🎊彩纸

80
2px
5px
中速
#0a0a2e
#ffffff 双色
0.3 - 1.0
最小
最大
实时预览
✨ 星空
生成代码
HTML + CSS + JS · 复制即用
常见问题 & 知识点

CSS 粒子背景是通过纯 CSS(配合少量 JavaScript)在网页背景中生成动态粒子效果的技术。常见应用包括:网站 Hero 区域背景装饰、登录页动态背景、节日主题页面(雪花、樱花)、品牌氛围营造等。相比 Canvas 方案,CSS 粒子更轻量,兼容性好,且对开发者也更友好。

合理使用粒子背景对性能影响很小。建议:粒子数量控制在 30-100 个之间;使用 will-change: transform, opacity 提示浏览器优化;使用 pointer-events: none 让粒子不阻挡用户交互;避免在移动端使用过多粒子(建议≤50个);使用 CSS @keyframes 动画而非 JavaScript 逐帧动画,可利用 GPU 加速。

当然可以!生成的代码是自包含的,包含完整的 CSS 动画定义和 JavaScript 粒子生成逻辑。你只需要在 HTML 中放置一个指定 ID 的容器元素,然后粘贴代码即可。代码不依赖任何第三方库,兼容所有现代浏览器(Chrome、Firefox、Safari、Edge)。建议将 <style> 放入 <head>,将 <script> 放在 </body> 之前。

完全支持移动端。CSS 粒子动画在移动浏览器上同样流畅。建议在移动端减少粒子数量(推荐 20-40 个),并适当降低动画复杂度。本工具生成的代码包含响应式适配建议,你可以根据屏幕宽度动态调整粒子数量。iOS Safari 和 Android Chrome 均经过充分测试。

有几种方法修改粒子形状:1) 使用 border-radius 创建圆形、椭圆或不规则形状;2) 使用 Unicode 字符(如 ★、❤、●)配合 content 属性;3) 使用 CSS clip-path 裁剪出星形、心形等多边形;4) 使用 SVG 或 emoji 作为粒子内容。本工具生成的代码中,粒子使用 border-radius: 50% 创建圆形,你可以自由修改。

CSS 粒子:优点包括代码简洁、易于修改样式、GPU 加速动画流畅、与页面其他元素自然融合;缺点是不适合超大量粒子(>300个)、交互性有限。Canvas 粒子:优点包括可处理海量粒子(数千个)、支持复杂物理模拟、可精确控制每个粒子;缺点是代码复杂度高、样式调整不便、需要 JavaScript 持续运行。对于装饰性背景,CSS 粒子是更优选择
`; codeOutput.text(code); } function generateKeyframesCSS(cfg, animList) { let css = ''; if (cfg.animationType === 'twinkle') { css += ` @keyframes star-twinkle-1 { 0%, 100% { opacity: ${cfg.opacityMin}; transform: scale(0.8); } 40% { opacity: ${cfg.opacityMax}; transform: scale(1.25); } 70% { opacity: ${(cfg.opacityMin + cfg.opacityMax) / 2}; transform: scale(0.9); } } @keyframes star-twinkle-2 { 0%, 100% { opacity: ${(cfg.opacityMin + cfg.opacityMax) / 2}; transform: scale(0.9); } 30% { opacity: ${cfg.opacityMax}; transform: scale(1.35); } 60% { opacity: ${cfg.opacityMin}; transform: scale(0.75); } 85% { opacity: ${cfg.opacityMax * 0.8}; transform: scale(1.1); } }`; } else if (cfg.animationType === 'rise') { css += ` @keyframes bubble-rise-1 { 0% { transform: translateY(0) translateX(0) scale(1); opacity: ${cfg.opacityMax}; } 70% { opacity: ${cfg.opacityMin + 0.1}; } 100% { transform: translateY(-110vh) translateX(30px) scale(0.4); opacity: 0; } } @keyframes bubble-rise-2 { 0% { transform: translateY(0) translateX(0) scale(0.8); opacity: ${cfg.opacityMax * 0.8}; } 50% { opacity: ${cfg.opacityMin + 0.15}; } 100% { transform: translateY(-110vh) translateX(-40px) scale(0.3); opacity: 0; } } @keyframes bubble-rise-3 { 0% { transform: translateY(0) translateX(0) scale(1.1); opacity: ${cfg.opacityMax}; } 60% { transform: translateY(-60vh) translateX(15px) scale(0.6); opacity: ${cfg.opacityMin + 0.2}; } 100% { transform: translateY(-110vh) translateX(-20px) scale(0.2); opacity: 0; } }`; } else if (cfg.animationType === 'fall') { css += ` @keyframes snow-fall-1 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax}; } 100% { transform: translateY(110vh) translateX(60px) rotate(360deg); opacity: ${cfg.opacityMin}; } } @keyframes snow-fall-2 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax * 0.9}; } 100% { transform: translateY(110vh) translateX(-50px) rotate(-300deg); opacity: ${cfg.opacityMin}; } } @keyframes snow-fall-3 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax}; } 100% { transform: translateY(110vh) translateX(80px) rotate(420deg); opacity: ${cfg.opacityMin * 0.8}; } }`; } else if (cfg.animationType === 'float') { css += ` @keyframes firefly-float-1 { 0% { transform: translate(0,0) scale(1); opacity: ${cfg.opacityMin}; } 25% { transform: translate(35px,-25px) scale(1.4); opacity: ${cfg.opacityMax}; } 50% { transform: translate(-20px,-45px) scale(0.7); opacity: ${cfg.opacityMin + 0.1}; } 75% { transform: translate(-35px,-10px) scale(1.2); opacity: ${cfg.opacityMax * 0.7}; } 100% { transform: translate(0,0) scale(1); opacity: ${cfg.opacityMin}; } } @keyframes firefly-float-2 { 0% { transform: translate(0,0) scale(0.9); opacity: ${cfg.opacityMin + 0.1}; } 30% { transform: translate(-30px,-30px) scale(1.5); opacity: ${cfg.opacityMax}; } 60% { transform: translate(25px,-50px) scale(0.6); opacity: ${cfg.opacityMin}; } 85% { transform: translate(20px,-5px) scale(1.1); opacity: ${cfg.opacityMax * 0.6}; } 100% { transform: translate(0,0) scale(0.9); opacity: ${cfg.opacityMin + 0.1}; } } @keyframes firefly-float-3 { 0% { transform: translate(0,0) scale(1.1); opacity: ${cfg.opacityMax * 0.5}; } 20% { transform: translate(20px,-15px) scale(1.6); opacity: ${cfg.opacityMax}; } 55% { transform: translate(-40px,-35px) scale(0.8); opacity: ${cfg.opacityMin}; } 80% { transform: translate(-10px,-20px) scale(1.3); opacity: ${cfg.opacityMax * 0.7}; } 100% { transform: translate(0,0) scale(1.1); opacity: ${cfg.opacityMax * 0.5}; } }`; } else if (cfg.animationType === 'petal-fall') { css += ` @keyframes petal-fall-1 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax}; } 100% { transform: translateY(110vh) translateX(70px) rotate(540deg); opacity: ${cfg.opacityMin}; } } @keyframes petal-fall-2 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax * 0.85}; } 100% { transform: translateY(110vh) translateX(-60px) rotate(-480deg); opacity: ${cfg.opacityMin}; } } @keyframes petal-fall-3 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax}; } 100% { transform: translateY(110vh) translateX(90px) rotate(600deg); opacity: ${cfg.opacityMin * 0.7}; } }`; } else if (cfg.animationType === 'confetti-fall') { css += ` @keyframes confetti-fall-1 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax}; } 100% { transform: translateY(110vh) translateX(50px) rotate(720deg); opacity: ${cfg.opacityMin}; } } @keyframes confetti-fall-2 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax * 0.9}; } 100% { transform: translateY(110vh) translateX(-70px) rotate(-600deg); opacity: ${cfg.opacityMin}; } } @keyframes confetti-fall-3 { 0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: ${cfg.opacityMax}; } 100% { transform: translateY(110vh) translateX(100px) rotate(900deg); opacity: ${cfg.opacityMin * 0.6}; } }`; } return css; } // 事件绑定 tool.find('.preset-btn').on('click', function() { const presetKey = $(this).data('preset'); if (presetKey && presets[presetKey]) { applyPreset(presetKey); } }); // 参数变化时更新预览 const debouncedUpdate = debounce(function() { const cfg = getUIParams(); currentConfig = { ...currentConfig, ...cfg }; updateParamLabels(cfg); generateParticles(); updateCodeOutput(); }, 300); tool.find('#pt-count, #pt-min-size, #pt-max-size, #pt-speed, #pt-opacity-min, #pt-opacity-max').on('input', function() { const cfg = getUIParams(); updateParamLabels(cfg); debouncedUpdate(); }); tool.find('#pt-bg-color, #pt-particle-color, #pt-particle-color2').on('input', function() { const cfg = getUIParams(); tool.find('#pt-bg-color-hex').text(cfg.bgColor); tool.find('#pt-particle-color-hex').text(cfg.particleColor); preview.css('background', cfg.bgColor); debouncedUpdate(); }); tool.find('#pt-glow').on('change', function() { debouncedUpdate(); }); tool.find('#pt-refresh-btn').on('click', function() { const cfg = getUIParams(); currentConfig = { ...currentConfig, ...cfg }; updateParamLabels(cfg); generateParticles(); updateCodeOutput(); const btn = $(this); btn.html(' 已刷新'); setTimeout(() => btn.html(' 刷新预览'), 1000); }); // 复制按钮 copyBtn.on('click', function() { const code = codeOutput.text(); if (navigator.clipboard) { navigator.clipboard.writeText(code).then(() => { showCopySuccess(); }).catch(() => { fallbackCopy(code); }); } else { fallbackCopy(code); } }); function fallbackCopy(text) { const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); showCopySuccess(); } catch(e) {} document.body.removeChild(ta); } function showCopySuccess() { copyBtn.addClass('copied'); copyBtn.html(' 已复制'); setTimeout(() => { copyBtn.removeClass('copied'); copyBtn.html(' 复制'); }, 1800); } function debounce(fn, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } // 窗口大小变化时重建粒子 let resizeTimer; $(window).on('resize', function() { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { generateParticles(); }, 400); }); // 初始化 function init() { applyPreset('stars'); generateParticles(); updateCodeOutput(); } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();