本文介绍如何使用JavaScript实现一个动态的星空图效果,主要利用HTML5 Canvas技术,通过JavaScript编写动画循环,生成随机位置、大小和透明度的星星,背景使用深邃的渐变色模拟夜空,并结合鼠标交互实现星星闪烁或连线效果,营造出沉浸式的视觉体验。
使用 JavaScript 与 Canvas 的 3D 粒子特效全解析
在网页设计和前端开发中,星空图一直是一个极具吸引力的视觉元素,它既能营造出深邃、静谧的氛围,又能通过动态的粒子效果展现出现代科技感,虽然可以使用现成的图片作为背景,但使用 JS实现星空图 往往能带来更流畅的交互体验和更高的可定制性。
本文将详细介绍如何使用 HTML5 Canvas 结合 JavaScript,打造一个逼真的、具有 3D 纵深感的星空穿梭动画。
核心原理:透视投影
要实现 3D 星空效果,我们并不需要引入庞大的 3D 引擎(如 Three.js),利用 JavaScript 的数学计算能力,在 2D 画布上模拟 3D 透视即可。
核心逻辑如下:
- 空间坐标:定义星星在 3D 空间中的坐标 $(x, y, z)$。
- 深度变化:让星星沿着 Z 轴(深度方向)向屏幕移动($z$ 值减小)。
- 透视投影:将 3D 坐标转换为 2D 屏幕坐标 $(sx, sy)$,公式大致为: $$sx = x / z \times \text{scale} + \text{centerX}$$ $$sy = y / z \times \text{scale} + \text{centerY}$$ 随着 $z$ 值变小(星星靠近屏幕),星星在屏幕上的位置会扩散,从而产生“向远处飞去”的视觉效果。
代码实现步骤
下面是一个完整的、可直接运行的代码示例,它包含星星的生成、运动逻辑、鼠标交互以及窗口自适应功能。
HTML 结构
我们需要一个全屏的 Canvas 元素。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">JS实现星空图 - 3D穿梭效果</title>
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden; /* 防止出现滚动条 */
background-color: #000; /* 黑色背景 */
}
canvas {
display: block;
}
</style>
</head>
<body>
<canvas id="starCanvas"></canvas>
<script>
// JavaScript 代码将在下方
</script>
</body>
</html>
JavaScript 逻辑
我们将创建一个 Star 类来管理每一颗星星的状态,并在 animate 函数中实现动画循环。
const canvas = document.getElementById('starCanvas');
const ctx = canvas.getContext('2d');
let width, height, centerX, centerY;
let stars = [];
const STAR_COUNT = 800; // 星星数量
const SPEED = 5; // 飞行速度
// 初始化画布尺寸
function init() {
width = window.innerWidth;
height = window.innerHeight;
centerX = width / 2;
centerY = height / 2;
canvas.width = width;
canvas.height = height;
}
// 星星类
class Star {
constructor() {
this.reset(true);
}
// 重置星星位置
// initial 参数用于判断是否是初始化(如果是初始化,z轴随机分布;否则z轴在远处)
reset(initial = false) {
this.x = (Math.random() - 0.5) * width * 2; // x 轴随机范围扩大,防止边缘空白
this.y = (Math.random() - 0.5) * height * 2;
this.z = initial ? Math.random() * width : width; // z 轴深度
this.pz = this.z; // 上一帧的 z 值,用于绘制尾迹
}
update() {
// z 轴减小,模拟星星向屏幕飞来
this.z -= SPEED;
// 如果星星飞到了屏幕后面(z <= 0),重置它
if (this.z <= 0) {
this.reset();
}
}
draw() {
// 透视投影公式
// sx: 屏幕 x 坐标
const sx = (this.x / this.z) * centerX + centerX;
// sy: 屏幕 y 坐标
const sy = (this.y / this.z) * centerX + centerY;
// 计算星星的大小:距离越近(z越小),星星越大
const r = (1 - this.z / width) * 3;
// 绘制星星
ctx.beginPath();
ctx.fillStyle = `rgba(255, 255, 255, ${1 - this.z / width})`;
ctx.arc(sx, sy, r, 0, Math.PI * 2);
ctx.fill();
// 绘制简单的尾迹效果(可选)
// 通过计算上一帧的位置,画出一条细线
const px = (this.x / this.pz) * centerX + centerX;
const py = (this.y / this.pz) * centerX + centerY;
ctx.beginPath();
ctx.strokeStyle = `rgba(255, 255, 255, ${0.5 * (1 - this.z / width)})`;
ctx.lineWidth = r;
ctx.moveTo(px, py);
ctx.lineTo(sx, sy);
ctx.stroke();
// 更新上一帧的 z 值
this.pz = this.z;
}
}
// 初始化星星数组
function createStars() {
stars = [];
for (let i = 0; i < STAR_COUNT; i++) {
stars.push(new Star());
}
}
// 动画循环
function animate() {
// 清空画布,使用半透明黑色可以产生拖尾效果,这里完全清空保持清晰
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, width, height);
stars.forEach(star => {
star.update();
star.draw();
});
requestAnimationFrame(animate);
}
// 监听窗口大小变化
window.addEventListener('resize', () => {
init();
createStars();
});
// 启动
init();
createStars();
animate();
进阶优化技巧
为了让星空图看起来更加专业,你可以尝试以下优化:
- 颜色变化:星星不仅仅是白色的,根据深度或速度,可以给星星添加颜色,例如从中心的亮白渐变到边缘的淡蓝或淡紫。
- 鼠标交互:让星空随着鼠标的移动产生轻微的偏移,或者让鼠标位置成为透视的中心点,而不是固定的屏幕中心。
- 不同速度层级:创建多个星星数组,赋予它们不同的飞行速度($SPEED$),从而模拟视差滚动效果,增强 3D 纵深感。
- 性能优化:如果星星数量极大(如 10000+),可以使用 WebGL,但在大多数普通网页场景下,上述 Canvas 2D 方案足以达到每秒 60 帧的流畅度。
通过 JS实现星空图,我们不仅掌握了一个经典的图形学算法,还能为网页增添无限的魅力,希望这篇文章能激发你的灵感,去创造属于自己的星空!
标签: #JavaScript #Canvas #星空 #粒子动画