5分钟搞定!用Canvas+JS打造超炫星空背景(附完整代码)

张开发
2026/4/4 1:24:47 15 分钟阅读
5分钟搞定!用Canvas+JS打造超炫星空背景(附完整代码)
5分钟实现星空动效Canvas与JavaScript的浪漫邂逅星空背景总能唤起人们对宇宙的无限遐想。想象一下当访客打开你的个人网站或作品集页面迎面而来的不是单调的纯色背景而是一片缓缓旋转的璀璨星河——这种视觉冲击力足以让人瞬间记住你的作品。本文将带你用最简洁的方式实现这样一个既美观又轻量的星空动画效果。1. 为什么选择Canvas实现星空效果在网页中实现动态背景开发者通常有几种选择GIF、CSS动画、SVG或Canvas。相比之下Canvas方案具有独特优势性能卓越Canvas直接操作像素避免DOM操作开销即使渲染上千颗星星也能保持流畅可控性强每颗星星的位置、大小、亮度都可单独控制实现丰富的视觉效果体积轻量不需要加载额外资源文件全部效果由代码实现自适应自动适应不同屏幕尺寸保持显示效果一致// 简单Canvas绘制示例 const canvas document.getElementById(stars); const ctx canvas.getContext(2d); canvas.width window.innerWidth; canvas.height window.innerHeight; // 绘制一颗星星 ctx.fillStyle white; ctx.beginPath(); ctx.arc(100, 100, 2, 0, Math.PI * 2); ctx.fill();2. 星空效果的核心实现步骤2.1 初始化Canvas画布首先需要设置Canvas元素并获取绘图上下文。这一步的关键是确保Canvas尺寸与视窗匹配!-- HTML结构 -- canvas idstarfield/canvas style #starfield { position: fixed; top: 0; left: 0; z-index: -1; width: 100vw; height: 100vh; } /style// JavaScript初始化 const canvas document.getElementById(starfield); const ctx canvas.getContext(2d); function resizeCanvas() { canvas.width window.innerWidth; canvas.height window.innerHeight; } window.addEventListener(resize, resizeCanvas); resizeCanvas();2.2 创建星星对象模型每颗星星都是独立的实体具有自己的属性属性说明取值范围x水平位置0 - canvas宽度y垂直位置0 - canvas高度radius半径大小1 - 5像素velocity移动速度0.1 - 0.5alpha透明度0.3 - 1.0class Star { constructor(canvasWidth, canvasHeight) { this.x Math.random() * canvasWidth; this.y Math.random() * canvasHeight; this.radius Math.random() * 3 1; this.velocity Math.random() * 0.4 0.1; this.alpha Math.random() * 0.7 0.3; } }2.3 实现动画循环使用requestAnimationFrame实现平滑动画const stars Array(200).fill().map(() new Star(canvas.width, canvas.height)); function animate() { ctx.fillStyle rgba(8, 8, 16, 0.2); ctx.fillRect(0, 0, canvas.width, canvas.height); stars.forEach(star { star.y star.velocity; if (star.y canvas.height) { star.y 0; star.x Math.random() * canvas.width; } ctx.beginPath(); ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2); ctx.fillStyle rgba(255, 255, 255, ${star.alpha}); ctx.fill(); }); requestAnimationFrame(animate); } animate();3. 进阶效果三维感星空实现要让星空更具层次感可以模拟不同距离的星星近景星星移动速度快、尺寸大、亮度高中景星星中等速度、中等大小远景星星移动缓慢、尺寸小、亮度低class AdvancedStar { constructor(canvasWidth, canvasHeight) { this.z Math.random() * 0.5 0.5; // 深度值(0.5-1.0) this.x Math.random() * canvasWidth; this.y Math.random() * canvasHeight; this.radius this.z * 3; // 远处星星更小 this.speed (1 - this.z) * 2; // 远处星星移动更慢 } update() { this.y this.speed; if (this.y canvas.height) { this.y 0; this.x Math.random() * canvas.width; } } draw(ctx) { const size this.radius * this.z; ctx.beginPath(); ctx.arc(this.x, this.y, size, 0, Math.PI * 2); ctx.fillStyle rgba(255, 255, 255, ${this.z}); ctx.fill(); } }4. 性能优化与实用技巧4.1 减少绘制操作使用clearRect替代重复填充背景批量绘制相同颜色的星星对静态背景使用缓存// 优化后的绘制逻辑 function optimizedDraw() { ctx.clearRect(0, 0, canvas.width, canvas.height); // 按颜色分组绘制 const starsByColor {}; stars.forEach(star { const colorKey star.color.toString(); if (!starsByColor[colorKey]) { starsByColor[colorKey] []; } starsByColor[colorKey].push(star); }); Object.entries(starsByColor).forEach(([color, starGroup]) { ctx.fillStyle color; ctx.beginPath(); starGroup.forEach(star { ctx.moveTo(star.x star.radius, star.y); ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2); }); ctx.fill(); }); }4.2 响应式设计考量星星数量根据屏幕尺寸动态调整移动端减少粒子数量添加防抖的resize事件处理function getOptimalStarCount() { const pixelCount window.innerWidth * window.innerHeight; const baseCount 1000; const maxCount 2000; // 每100万像素增加500颗星星最多2000颗 return Math.min( baseCount Math.floor(pixelCount / 1e6) * 500, maxCount ); } let stars []; function resetStarfield() { const count getOptimalStarCount(); stars Array(count).fill().map(() new Star(canvas.width, canvas.height)); } // 防抖的resize处理 let resizeTimeout; window.addEventListener(resize, () { clearTimeout(resizeTimeout); resizeTimeout setTimeout(() { resizeCanvas(); resetStarfield(); }, 200); });5. 创意扩展让星空更生动5.1 添加流星效果class ShootingStar { constructor() { this.reset(); this.angle Math.PI / 4; this.length Math.random() * 50 50; } reset() { this.x Math.random() * canvas.width; this.y Math.random() * canvas.height * 0.2; this.speed Math.random() * 10 5; this.size Math.random() * 2 1; this.life 1; this.decay Math.random() * 0.02 0.01; } update() { this.x this.speed * Math.cos(this.angle); this.y this.speed * Math.sin(this.angle); this.life - this.decay; if (this.life 0 || this.x canvas.width || this.y canvas.height) { this.reset(); } } draw(ctx) { ctx.strokeStyle rgba(255, 255, 255, ${this.life}); ctx.lineWidth this.size; ctx.beginPath(); ctx.moveTo(this.x, this.y); ctx.lineTo( this.x - this.length * Math.cos(this.angle), this.y - this.length * Math.sin(this.angle) ); ctx.stroke(); } }5.2 交互式星空添加鼠标交互让星星对用户操作产生反应canvas.addEventListener(mousemove, (e) { const mouseX e.clientX; const mouseY e.clientY; stars.forEach(star { const dx star.x - mouseX; const dy star.y - mouseY; const distance Math.sqrt(dx * dx dy * dy); if (distance 100) { star.x dx * 0.02; star.y dy * 0.02; } }); });实现星空效果最令人满意的部分是看到简单的代码转化为生动的视觉体验。当第一颗星星在画布上亮起时那种成就感是前端开发独有的快乐。在实际项目中我发现将星星数量控制在800-1200之间既能保证视觉效果又不会对性能造成明显影响。

更多文章