Canvas实例篇:十二星座之天秤座

article/2025/6/23 3:09:17

Canvas实例篇:十二星座之天秤座

  • 前言
  • 效果预览
  • 代码实现
  • 代码说明
    • 星座特定星
  • 结语

前言

星座总给人浪漫而神秘的感觉,如何用代码还原星空中的浪漫?本文将通过 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绘制其余星座。对于文章中错误的地方或者有任何问题,欢迎在评论区留言分享!


http://www.hkcw.cn/article/YwjxEACjbq.shtml

相关文章

VIP》》IP地址漂移

IP地址漂移&#xff0c;就是一个虚拟的IP地址&#xff0c;能够在不同的物理服务器或网络接口之家来回转换&#xff0c;所以当你或者其他的网络设备跟这个虚拟IP地址连接的时候&#xff0c;并不会察觉到设备的转换。这对于网络流量调度&#xff0c;服务器负载均衡的使用意义重大…

【C语言】讲解 程序分配的区域(新手)

目录 代码区 数据区 堆区 栈区 常量区 重点比较一下堆区与 栈区 总结&#xff1a; 前言&#xff1a; C语言程序的内存分配区域是理解其运行机制的重要部分。根据提供的多条证据&#xff0c;我们可以总结出C语言程序在运行时主要涉及以下五个关键内存区域&#xff1a; 代…

时间序列预测入门喂饭教程,python代码示例

目录 前言一、基本原理1、啥是时间序列&#xff1f;2、预测前的准备什么材料&#xff1f;3、搭建你的预测工具&#xff08;模型&#xff09; 二、建模模拟实战&#xff1a;用Python搭个简单模型**Step 1&#xff1a;先把需要的工具库准备好****Step 2&#xff1a;生成一组模拟的…

BLE 广播与扫描机制详解:如何让设备“被看见”?

在 BLE 通信中,“广播”是设备展示自己的方式,“扫描”是发现外设的入口。 作为 BLE 协议的核心机制之一,广播与扫描的设计直接影响通信的稳定性、功耗与连接效率。本篇将从 BLE 广播/扫描原理、数据结构、事件流程到调试技巧全面展开,配合实战案例深入讲解 BLE 设备“可被…

小程序使用npm包的方法

有用的链接 npm init -y 这个命令很重要, 会初始化 package.json 再重新打开微信小程序开发工具 选择工具中npm构建 在程序中引用时在main.js中直接使用包名的方式引用即可 如安装的是generator包&#xff0c;npm构建后就会生成 const myPackage require(***-generato…

Java 单例模式详解

目录 1. 饿汉式&#xff08;Eager Initialization&#xff09; 2. 懒汉式&#xff08;Lazy Initialization&#xff09; 3. 懒汉式 同步锁&#xff08;线程安全&#xff09; 4. 双重检查锁&#xff08;Double-Checked Locking&#xff09; 5. 静态内部类&#xff08;推荐…

大模型应用开发之预训练

预训练是研发大语言模型的第一个训练阶段&#xff0c;通过在大规模语料上进行预训练&#xff0c;大语言模型可以获得通用的语言理解与生成能力&#xff0c;掌握较为广泛的世界知识&#xff0c;具备解决众多下游任务的性能潜力 一、数据预处理 1. 数据的收集 1&#xff09;通…

属性映射框架-MapStruct

属性映射框架-MapStruct 文章目录 属性映射框架-MapStruct一、作用二、MapStruct 简介2.1 是什么2.2 竞品框架2.3 适合场景 三、入门案例3.1 项目需求3.2 代码实现 四、入门案例解析五、MapStruct 实战5.1 当属性正常映射时5.2 当某个属性要忽略映射5.3 当某个属性要求设置默认…

switch-case判断

switch-case判断 #include <stdio.h> int main() {int type;printf("请输入你的选择&#xff1a;\n");scanf("%d",&type);getchar();switch (type){case 1:printf("你好&#xff01;");break;case 2:printf("早上好&#xff01;…

德拜温度热容推导

目录 一、背景与基本假设 一、态密度的定义 二、从波矢空间出发 三、振动模式数与波矢体积关系 四、模式总数计算 五、态密度求导 六、德拜频率确定与归一化条件 二、内能表达式的推导 三、态密度代入与变量替换 四、求比热容 五、低温时&#xff08;&#xff09; …

Android Framework层RenderThread指令队列深度调试实战指南

简介 在移动应用开发过程中,UI渲染性能优化是提升用户体验的关键环节。Android的RenderThread作为硬件加速渲染的核心线程,其指令队列的处理效率直接影响着应用的流畅度。本篇文章将深入探讨如何在Android Framework层对RenderThread指令队列进行调试和优化,帮助开发者解决…

BLE协议全景图:从0开始理解低功耗蓝牙

BLE(Bluetooth Low Energy)作为一种针对低功耗场景优化的通信协议,已经广泛应用于智能穿戴、工业追踪、智能家居、医疗设备等领域。 本文是《BLE 协议实战详解》系列的第一篇,将从 BLE 的发展历史、协议栈结构、核心机制和应用领域出发,为后续工程实战打下全面认知基础。 …

深入理解C#异步编程:原理、实践与最佳方案

在现代软件开发中&#xff0c;应用程序的性能和响应能力至关重要。特别是在处理I/O密集型操作&#xff08;如网络请求、文件读写、数据库查询&#xff09;时&#xff0c;传统的同步编程方式会导致线程阻塞&#xff0c;降低程序的吞吐量。C# 的异步编程模型&#xff08;async/aw…

如何查看电脑电池性能

检查电脑电池性能的方法如下&#xff1a; 按下winR键&#xff0c;输入cmd回车&#xff0c;进入命令行窗口 在命令行窗口输入powercfg /batteryreport 桌面双击此电脑&#xff0c;把刚刚复制的路径粘贴到文件路径栏&#xff0c;然后回车 回车后会自动用浏览器打开该报告 红…

高考加油!UI界面生成器!

这个高考助力标语生成器具有以下特点&#xff1a; 视觉设计&#xff1a;采用了蓝色为主色调&#xff0c;搭配渐变背景和圆形装饰元素&#xff0c;营造出宁静而充满希望的氛围&#xff0c;非常适合高考主题。 标语生成&#xff1a;内置了超过 100 条精心挑选的高考加油标语&a…

fork函数小解

学了好久终于搞懂fork函数的一些作用 1. fork函数作用&#xff1a;用于创建新的子进程 这是fork最根本的功能&#xff0c;在父进程里创建新的子进程、 但是创建新的子进程之后呢&#xff1f; 子进程和父进程的关系是什么样的&#xff1f; 为什么fork得到的子进程返回值为0&am…

5月31日day41打卡

简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 → Batch…

配置前端控制器

一、DispatcherServlet 详解 在使用 Spring MVC 框架构建 Web 应用时&#xff0c;DispatcherServlet是整个请求处理流程的核心。本文将深入解析DispatcherServlet的作用、工作原理及其在 Spring MVC 架构中的关键地位。 1.DispatcherServlet 是什么&#xff1f; DispatcherS…

使用PowerBI个人网关定时刷新数据

使用PowerBI个人网关定时刷新数据 PowerBI desktop连接mysql&#xff0c;可以设置定时刷新数据或在PowerBI服务中手动刷新数据,步骤如下&#xff1a; 第一步&#xff1a; 下载网关。以个人网关为例&#xff0c;如图 第二步&#xff1a; 双击网关&#xff0c;点击下一步&…

Dest建筑能耗模拟仿真功能简介

Dest建筑能耗模拟仿真功能简介 全球建筑能耗占终端能源消费的30%以上&#xff0c;掌握建筑能耗模拟是参与绿色建筑认证&#xff08;如LEED、WELL&#xff09;、超低能耗设计、既有建筑节能改造的必备能力。DEST作为国内主流建筑能耗模拟工具&#xff0c;广泛应用于设计院、咨询…