前言
星座总给人浪漫而神秘的感觉,如何用代码还原星空中的浪漫?本文将通过 Canvas 技术,讲述如何实现一个可交互的天秤座星空图,包含星星闪烁、星座连线、动态效果控制等功能。
效果预览
代码实现
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天秤座星空图</title>
<style>
body,
html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: #000;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
.constellation-info {
position: absolute;
bottom: 20px;
left: 20px;
color: #fff;
font-family: Arial, sans-serif;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
}
.controls {
position: absolute;
top: 20px;
right: 20px;
color: white;
font-family: Arial, sans-serif;
}
button {
background: rgba(255, 255, 255, 0.1);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 5px 10px;
margin: 5px;
cursor: pointer;
border-radius: 3px;
}
button:hover {
background: rgba(255, 255, 255, 0.2);
}
</style>
</head>
<body>
<canvas id="starCanvas"></canvas>
<div class="constellation-info">
<h3>天秤座 (9月23日 ~ 10月23日)</h3>
<p>黄道十二宫之一</p>
<p>象征平衡与正义的星座</p>
</div>
<div class="controls">
<button id="toggleLines">显示/隐藏连线</button>
<button id="toggleNames">显示/隐藏星名</button>
<button id="toggleAnimation">暂停/继续动画</button>
</div>
<script>
// 获取Canvas元素和绘图上下文
const canvas = document.getElementById('starCanvas');
const ctx = canvas.getContext('2d');
// 设置Canvas尺寸为窗口大小
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// 存储星星的数组
const stars = [];
// 天秤座主星数据
const libraStars = [{
name: "氐宿四",
x: 0.43,
y: 0.3,
magnitude: 2.7,
color: "#FFFFC3"
},{
name: "氐宿一",
x: 0.53,
y: 0.45,
magnitude: 3.9,
color: "#42A5F5"
},{
name: "氐宿三",
x: 0.35,
y: 0.4,
magnitude: 2.6,
color: "#FFA726"
},{
name: "氐宿增一",
x: 0.5,
y: 0.62,
magnitude: 4.6,
color: "#FFF59D"
},{
name: "折威七",
x: 0.53,
y: 0.66,
magnitude: 4.4,
color: "#64B5F6"
},{
name: "氐宿二",
x: 0.38,
y: 0.51,
magnitude: 4.0,
color: "#FFCCBC"
},{
name: "氐宿五",
x: 0.365,
y: 0.575,
magnitude: 4.3,
color: "#FFCC80"
},{
name: "氐宿增五",
x: 0.35,
y: 0.64,
magnitude: 4.8,
color: "#E6EE9C"
}
];
// 天秤座星座连线
const starConnections = [
// 秤杆
[0 ,1],
[1, 2],
[2, 0],
// 秤盘
[1, 3],
[3, 4],
[2,5],
[5,6],
[6,7]
];
// 初始化随机星星
function initStars(count) {
for (let i = 0; i < count; i++) {
stars.push({
x: Math.random(),
y: Math.random(),
size: Math.random() * 2,
brightness: Math.random(),
twinkleSpeed: Math.random() * 0.01
});
}
// 添加星座星星
libraStars.forEach(star => {
stars.push({
x: star.x,
y: star.y,
size: star.magnitude,
brightness: 1,
isConstellation: true,
name: star.name,
color: star.color
});
});
}
// 绘制星空
function drawStars() {
// 清空画布
ctx.fillStyle = '#000a1a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制背景星星
stars.forEach(star => {
if (!star.isConstellation) {
// 让星星闪烁
const twinkle = Math.sin(Date.now() * star.twinkleSpeed) * 0.5 + 0.5;
const alpha = star.brightness * twinkle;
ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`;
ctx.beginPath();
ctx.arc(
star.x * canvas.width,
star.y * canvas.height,
star.size,
0,
Math.PI * 2
);
ctx.fill();
}
});
// 绘制星座连线
if (showLines) {
ctx.strokeStyle = 'rgb(255, 255, 255)';
ctx.lineWidth = 3;
starConnections.forEach(connection => {
const startIndex = connection[0];
const endIndex = connection[1];
// 确保索引有效
if (startIndex < libraStars.length && endIndex < libraStars.length) {
const start = stars[stars.length - libraStars.length + startIndex];
const end = stars[stars.length - libraStars.length + endIndex];
ctx.beginPath();
// 判断画布
if (canvas.width > canvas.height) {
ctx.moveTo(start.x * canvas.width, start.y * canvas.height);
ctx.lineTo(end.x * canvas.width, end.y * canvas.height);
} else {
ctx.moveTo(start.y * canvas.width, (start.x + 0.1) * canvas.height);
ctx.lineTo(end.y * canvas.width, (end.x + 0.1) * canvas.height);
}
ctx.stroke();
}
});
}
// 绘制星座星星
libraStars.forEach((star, index) => {
const starObj = stars[stars.length - libraStars.length + index];
ctx.fillStyle = starObj.color;
ctx.beginPath();
// 判断画布
if (canvas.width > canvas.height) {
ctx.arc(
starObj.x * canvas.width,
starObj.y * canvas.height,
starObj.size + 0.5,
0,
Math.PI * 2
);
} else {
ctx.arc(
starObj.y * canvas.width,
(starObj.x + 0.1) * canvas.height,
starObj.size + 0.5,
0,
Math.PI * 2
);
}
ctx.fill();
// 添加星名
if (showNames) {
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.font = '12px Arial';
if (canvas.width > canvas.height) {
ctx.fillText(
starObj.name,
starObj.x * canvas.width + 8,
starObj.y * canvas.height - 8
);
} else {
ctx.fillText(
starObj.name,
starObj.y * canvas.width + 8,
(starObj.x + 0.1) * canvas.height + 8
);
}
}
});
}
// 动画循环
function animate() {
if (animationRunning) {
requestAnimationFrame(animate);
}
drawStars();
}
// 控制变量
let showLines = true;
let showNames = true;
let animationRunning = true;
// 初始化
initStars(2000);
animate();
// 添加按钮事件
document.getElementById('toggleLines').addEventListener('click', () => {
showLines = !showLines;
});
document.getElementById('toggleNames').addEventListener('click', () => {
showNames = !showNames;
});
document.getElementById('toggleAnimation').addEventListener('click', () => {
animationRunning = !animationRunning;
if (animationRunning) {
animate();
}
});
</script>
</body>
</html>
代码说明
星座特定星
// 天秤座主星数据
const libraStars = [{
name: "氐宿四",
x: 0.43,
y: 0.3,
magnitude: 2.7,
color: "#FFFFC3"
}, {
name: "氐宿一",
x: 0.53,
y: 0.45,
magnitude: 3.9,
color: "#42A5F5"
}, {
name: "氐宿三",
x: 0.35,
y: 0.4,
magnitude: 2.6,
color: "#FFA726"
}, {
name: "氐宿增一",
x: 0.5,
y: 0.62,
magnitude: 4.6,
color: "#FFF59D"
}, {
name: "折威七",
x: 0.53,
y: 0.66,
magnitude: 4.4,
color: "#64B5F6"
}, {
name: "氐宿二",
x: 0.38,
y: 0.51,
magnitude: 4.0,
color: "#FFCCBC"
}, {
name: "氐宿五",
x: 0.365,
y: 0.575,
magnitude: 4.3,
color: "#FFCC80"
}, {
name: "氐宿增五",
x: 0.35,
y: 0.64,
magnitude: 4.8,
color: "#E6EE9C"
}];
// 天秤座星座连线
const starConnections = [
// 秤杆
[0, 1],
[1, 2],
[2, 0],
// 秤盘
[1, 3],
[3, 4],
[2, 5],
[5, 6],
[6, 7]
];
结语
本文主要讲解了如何通过Canvas绘制天秤座星座图,后续会继续使用Canvas绘制其余星座。对于文章中错误的地方或者有任何问题,欢迎在评论区留言分享!