js实现星空图

admin 55 0
本文介绍如何使用JavaScript实现一个动态的星空图效果,主要利用HTML5 Canvas技术,通过JavaScript编写动画循环,生成随机位置、大小和透明度的星星,背景使用深邃的渐变色模拟夜空,并结合鼠标交互实现星星闪烁或连线效果,营造出沉浸式的视觉体验。

使用 JavaScript 与 Canvas 的 3D 粒子特效全解析

在网页设计和前端开发中,星空图一直是一个极具吸引力的视觉元素,它既能营造出深邃、静谧的氛围,又能通过动态的粒子效果展现出现代科技感,虽然可以使用现成的图片作为背景,但使用 JS实现星空图 往往能带来更流畅的交互体验和更高的可定制性。

本文将详细介绍如何使用 HTML5 Canvas 结合 JavaScript,打造一个逼真的、具有 3D 纵深感的星空穿梭动画。

核心原理:透视投影

要实现 3D 星空效果,我们并不需要引入庞大的 3D 引擎(如 Three.js),利用 JavaScript 的数学计算能力,在 2D 画布上模拟 3D 透视即可。

核心逻辑如下:

  1. 空间坐标:定义星星在 3D 空间中的坐标 $(x, y, z)$。
  2. 深度变化:让星星沿着 Z 轴(深度方向)向屏幕移动($z$ 值减小)。
  3. 透视投影:将 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();

进阶优化技巧

为了让星空图看起来更加专业,你可以尝试以下优化:

  1. 颜色变化:星星不仅仅是白色的,根据深度或速度,可以给星星添加颜色,例如从中心的亮白渐变到边缘的淡蓝或淡紫。
  2. 鼠标交互:让星空随着鼠标的移动产生轻微的偏移,或者让鼠标位置成为透视的中心点,而不是固定的屏幕中心。
  3. 不同速度层级:创建多个星星数组,赋予它们不同的飞行速度($SPEED$),从而模拟视差滚动效果,增强 3D 纵深感。
  4. 性能优化:如果星星数量极大(如 10000+),可以使用 WebGL,但在大多数普通网页场景下,上述 Canvas 2D 方案足以达到每秒 60 帧的流畅度。

通过 JS实现星空图,我们不仅掌握了一个经典的图形学算法,还能为网页增添无限的魅力,希望这篇文章能激发你的灵感,去创造属于自己的星空!

标签: #JavaScript #Canvas #星空 #粒子动画