HTML5 Canvas与JavaScript携手绘制动态星空背景

目录

一、程序代码

二、代码原理

三、运行效果


一、程序代码

html 复制代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>星空背景</title>
</head>
<body style="overflow-x:hidden;">
    <canvas id="canvas"></canvas> <!-- 创建一个画布元素 -->
</body>

<script>
    // 获取画布元素和2D上下文
	canvas = document.getElementById('canvas');
	ctx = canvas.getContext('2d'); 
	// 设置画布宽度和高度
	w = canvas.width = window.innerWidth;		
	h = canvas.height = window.innerHeight-50; 
	
	hue = 217; // 设定颜色
	stars = []; // 存储星星的数组
	count = 0,
	maxStars = 1500; // 星星数量

    // 创建用于渲染星星的小画布
	canvas2 = document.createElement('canvas');
	w2 = canvas2.width = 100;
	h2 = canvas2.height = 100;
	ctx2 = canvas2.getContext("2d");
	gradientCache = ctx2.createRadialGradient(w2 / 2, h2 / 2, 0, w2 / 2, h2 / 2, w2 / 2);
	gradientCache.addColorStop(0.025, '#fff');
	gradientCache.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)');
	gradientCache.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)');
	gradientCache.addColorStop(1, 'transparent');
	ctx2.fillStyle = gradientCache;
	ctx2.beginPath();
	ctx2.arc(w2 / 2, h2 / 2, w2 / 2, 0, Math.PI * 2);
	ctx2.fill();

    // 生成随机数
	function random(min, max) {
		if (arguments.length < 2) {
			max = min;
			min = 0;
		}
		if (min > max) {
			var hold = max;
			max = min;
			min = hold;
		}
		return Math.floor(Math.random() * (max - min + 1)) + min;
	}

    // 确定星星轨道半径
	function maxOrbit(x, y) {
		var max = Math.max(x, y), diameter = Math.round(Math.sqrt(max * max + max * max));
		return diameter / 2;
	}

    // 构造函数用于创建星星对象
	Star = function() {
		this.orbitRadius = random(maxOrbit(w, h));
		this.radius = random(60, this.orbitRadius) / 10;
		this.orbitX = w / 2;
		this.orbitY = h / 2;
		this.timePassed = random(2, maxStars);	
		this.speed = random(this.orbitRadius) / 120000;
		this.alpha = random(2, 10) / 10;
		count++;
		stars[count] = this;
	}

    // 在画布上绘制星星
	Star.prototype.draw = function() {
		x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX;
		y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY;
		twinkle = random(10);

		if (twinkle === 1 && this.alpha > 0) {
			this.alpha -= 0.05;
		} else if (twinkle === 2 && this.alpha < 1) {
			this.alpha += 0.05;
		}

		ctx.globalAlpha = this.alpha;
		ctx.drawImage(canvas2, x - this.radius / 2, y - this.radius / 2, this.radius, this.radius);
		this.timePassed += this.speed;
	}

    // 创建一定数量的星星对象
	for (var i = 0; i < maxStars; i++) {
		new Star();
	}

    // 开始绘制星空背景
	function start() {
		ctx.globalCompositeOperation = 'source-over';
		ctx.globalAlpha = 1;
		ctx.fillStyle = 'hsla(' + hue + ', 64%,6%,0.2)';
		ctx.fillRect(0, 0, w, h)

		ctx.globalCompositeOperation = 'lighter';
		for (var i = 1, l = stars.length; i < l; i++) {
			stars[i].draw();
		};
		window.requestAnimationFrame(start);
	}

	start(); // 调用开始函数
</script>
</html>

二、代码原理

这段代码通过 HTML5 的 <canvas> 元素和 JavaScript 实现了一个星空背景效果。首先,它在页面加载时创建了一个全屏大小的画布,并使用 JavaScript 生成了多个具有不同运动轨道的星星对象。每颗星星都具有随机的半径、位置、运动速度和闪烁效果。通过使用定时器和 requestAnimationFrame 方法,实现了星星的运动和闪烁效果,从而呈现出逼真的星空背景。整体效果是一个动态的、具有视差效果的星空背景,为网页增添了视觉吸引力。

  1. 首先是 HTML 结构部分:

    • 定义了一个 HTML 文档,并设置了字符集为 UTF-8。
    • 设置了页面的标题为"星空背景"。
    • 在 body 中定义了一个画布元素 <canvas>,并指定了一个 id 为 "canvas"。
  2. 紧接着是 JavaScript 部分:

    • 获取了 <canvas> 元素以及其 2D 绘图上下文。
    • 设置了画布的宽度和高度为窗口的宽度和高度减去 50。
    • 定义了一些变量,如颜色值、存储星星的数组、星星数量等。
  3. 创建用于渲染星星的小画布:

    • 创建了一个新的 <canvas> 元素作为缓存画布。
    • 设置了缓存画布的宽高,并获取其 2D 上下文。
    • 创建了一个径向渐变对象,定义了星星的颜色渐变规则。
    • 绘制了一个圆形填充的图案,代表星星的外观。
  4. 定义了两个辅助函数:

    • random(min, max) 用于生成指定范围内的随机数。
    • maxOrbit(x, y) 用于确定星星轨道的最大半径。
  5. 创建了一个构造函数 Star 用于创建星星对象:

    • 初始化了星星的轨道半径、半径大小、位置等属性。
    • 将每个创建的星星对象存储到 stars 数组中。
  6. 定义了 Star 原型对象的 draw 方法:

    • 根据时间变化计算星星的位置坐标。
    • 控制星星闪烁效果的透明度变化。
    • 使用缓存画布绘制星星。
    • 更新星星的时间,实现星星的运动效果。
  7. 创建了一定数量的星星对象,并将其存储在 stars 数组中。

  8. 定义了 start 函数开始绘制星空背景:

    • 设置了画布的全局合成操作模式和透明度。
    • 填充了一个半透明的矩形作为背景。
    • 设置了全局合成操作模式为 'lighter',实现星星的叠加效果。
    • 遍历所有星星对象,并调用其 draw 方法进行绘制。
    • 使用 window.requestAnimationFrame 实现动画效果。
  9. 调用 start 函数,开始绘制星空背景效果。

三、运行效果

相关推荐
理想不理想v几秒前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云11 分钟前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
aPurpleBerry1 小时前
JS常用数组方法 reduce filter find forEach
javascript
ZL不懂前端2 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x2 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落2 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
理想不理想v3 小时前
vue经典前端面试题
前端·javascript·vue.js
小阮的学习笔记3 小时前
Vue3中使用LogicFlow实现简单流程图
javascript·vue.js·流程图