太阳系运行模拟程序-html动画

太阳系运行模拟程序-html动画

by AI:

<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>交互式太阳系模拟器</title><style>body {margin: 0;overflow: hidden;background-color: #000;font-family: Arial, sans-serif;color: white;}canvas {display: block;}#info {position: absolute;top: 10px;left: 10px;background-color: rgba(0, 0, 0, 0.7);padding: 10px;border-radius: 5px;max-width: 300px;}#controls {position: absolute;bottom: 10px;left: 10px;background-color: rgba(0, 0, 0, 0.7);padding: 10px;border-radius: 5px;}button {background-color: #333;color: white;border: 1px solid #555;padding: 5px 10px;margin: 5px;cursor: pointer;}button:hover {background-color: #444;}#planet-info {position: absolute;right: 10px;top: 10px;background-color: rgba(0, 0, 0, 0.7);padding: 10px;border-radius: 5px;width: 250px;display: none;}</style>
</head>
<body><canvas id="solarSystem"></canvas><div id="info"><h2>太阳系模拟器</h2><p>鼠标拖动可以旋转视角</p><p>滚轮可以缩放</p><p>点击行星查看详细信息</p></div><div id="controls"><button id="speedUp">加速</button><button id="speedDown">减速</button><button id="pause">暂停/继续</button><button id="realScale">真实比例</button><button id="viewScale">可视比例</button></div><div id="planet-info"><h2 id="planet-name">行星名称</h2><p id="planet-desc">描述信息...</p><p>直径: <span id="planet-diameter"></span></p><p>与太阳距离: <span id="planet-distance"></span></p><p>轨道周期: <span id="planet-period"></span></p></div><script>// 初始化画布const canvas = document.getElementById('solarSystem');const ctx = canvas.getContext('2d');canvas.width = window.innerWidth;canvas.height = window.innerHeight;// 行星数据const planets = [{ name: "太阳", radius: 30, distance: 0, color: "#FDB813", speed: 0, desc: "太阳系的中心恒星", diameter: "1,392,700 km", orbitalPeriod: "" },{ name: "水星", radius: 5, distance: 60, color: "#A9A9A9", speed: 0.04, desc: "最靠近太阳的行星", diameter: "4,880 km", orbitalPeriod: "88 地球日" },{ name: "金星", radius: 9, distance: 90, color: "#E6E6FA", speed: 0.015, desc: "最热的行星,逆向自转", diameter: "12,104 km", orbitalPeriod: "225 地球日" },{ name: "地球", radius: 10, distance: 130, color: "#6B93D6", speed: 0.01, desc: "我们美丽的家园", diameter: "12,742 km", orbitalPeriod: "365.25 地球日", moons: [{ radius: 3, distance: 20, speed: 0.05 }] },{ name: "火星", radius: 7, distance: 180, color: "#C1440E", speed: 0.008, desc: "红色行星,可能有生命", diameter: "6,779 km", orbitalPeriod: "687 地球日", moons: [{ radius: 2, distance: 15, speed: 0.03 }, { radius: 1, distance: 25, speed: 0.02 }] },{ name: "木星", radius: 22, distance: 250, color: "#E3DCCB", speed: 0.002, desc: "太阳系最大的行星", diameter: "139,820 km", orbitalPeriod: "12 地球年", moons: Array(4).fill().map((_, i) => ({ radius: 3 + Math.random(), distance: 30 + i * 10, speed: 0.01 + Math.random() * 0.02 })) },{ name: "土星", radius: 19, distance: 320, color: "#F7EC9E", speed: 0.001, desc: "拥有美丽光环的气态巨行星", diameter: "116,460 km", orbitalPeriod: "29.5 地球年", rings: { inner: 25, outer: 40 }, moons: Array(7).fill().map((_, i) => ({ radius: 2 + Math.random(), distance: 25 + i * 8, speed: 0.01 + Math.random() * 0.02 })) },{ name: "天王星", radius: 15, distance: 380, color: "#D1E7E7", speed: 0.0007, desc: "侧向自转的冰巨星", diameter: "50,724 km", orbitalPeriod: "84 地球年", moons: Array(5).fill().map((_, i) => ({ radius: 2 + Math.random(), distance: 20 + i * 7, speed: 0.01 + Math.random() * 0.02 })) },{ name: "海王星", radius: 14, distance: 440, color: "#5B5DDF", speed: 0.0005, desc: "太阳系最外围的行星", diameter: "49,244 km", orbitalPeriod: "165 地球年", moons: Array(2).fill().map((_, i) => ({ radius: 2 + Math.random(), distance: 20 + i * 10, speed: 0.01 + Math.random() * 0.02 })) }];// 模拟状态let state = {time: 0,speed: 1,paused: false,scale: "view", // "view" or "real"rotationX: 0,rotationY: 0,zoom: 1,lastX: 0,lastY: 0,dragging: false,selectedPlanet: null};// 事件监听canvas.addEventListener('mousedown', (e) => {state.dragging = true;state.lastX = e.clientX;state.lastY = e.clientY;});canvas.addEventListener('mousemove', (e) => {if (state.dragging) {state.rotationY += (e.clientX - state.lastX) * 0.01;state.rotationX += (e.clientY - state.lastY) * 0.01;state.lastX = e.clientX;state.lastY = e.clientY;}});canvas.addEventListener('mouseup', () => {state.dragging = false;});canvas.addEventListener('wheel', (e) => {state.zoom -= e.deltaY * 0.001;state.zoom = Math.max(0.1, Math.min(2, state.zoom));});canvas.addEventListener('click', (e) => {const rect = canvas.getBoundingClientRect();const x = e.clientX - rect.left;const y = e.clientY - rect.top;// 检查是否点击了行星const clickedPlanet = checkPlanetClick(x, y);if (clickedPlanet) {state.selectedPlanet = clickedPlanet;showPlanetInfo(clickedPlanet);} else {state.selectedPlanet = null;document.getElementById('planet-info').style.display = 'none';}});// 控制按钮document.getElementById('speedUp').addEventListener('click', () => {state.speed *= 1.5;});document.getElementById('speedDown').addEventListener('click', () => {state.speed /= 1.5;});document.getElementById('pause').addEventListener('click', () => {state.paused = !state.paused;});document.getElementById('realScale').addEventListener('click', () => {state.scale = "real";});document.getElementById('viewScale').addEventListener('click', () => {state.scale = "view";});// 检查行星点击function checkPlanetClick(x, y) {const centerX = canvas.width / 2;const centerY = canvas.height / 2;for (let i = planets.length - 1; i >= 0; i--) {const planet = planets[i];const scaleFactor = state.scale === "real" ? 0.1 : 1;// 计算行星位置const angle = state.time * planet.speed;const planetX = centerX + Math.cos(angle) * planet.distance * state.zoom;const planetY = centerY + Math.sin(angle) * planet.distance * state.zoom * 0.5;// 考虑旋转const rotatedX = centerX + (planetX - centerX) * Math.cos(state.rotationY) - (planetY - centerY) * Math.sin(state.rotationY);const rotatedY = centerY + (planetX - centerX) * Math.sin(state.rotationY) + (planetY - centerY) * Math.cos(state.rotationY);// 检查点击const distance = Math.sqrt(Math.pow(x - rotatedX, 2) + Math.pow(y - rotatedY, 2));if (distance < planet.radius * state.zoom * scaleFactor) {return planet;}}return null;}// 显示行星信息function showPlanetInfo(planet) {const infoPanel = document.getElementById('planet-info');document.getElementById('planet-name').textContent = planet.name;document.getElementById('planet-desc').textContent = planet.desc;document.getElementById('planet-diameter').textContent = planet.diameter;document.getElementById('planet-distance').textContent = `${(planet.distance / 10).toFixed(1)} 天文单位`;document.getElementById('planet-period').textContent = planet.orbitalPeriod;infoPanel.style.display = 'block';}// 动画循环function animate() {if (!state.paused) {state.time += 0.01 * state.speed;}// 清除画布ctx.fillStyle = 'black';ctx.fillRect(0, 0, canvas.width, canvas.height);// 绘制星空背景drawStars();const centerX = canvas.width / 2;const centerY = canvas.height / 2;const scaleFactor = state.scale === "real" ? 0.1 : 1;// 绘制行星planets.forEach(planet => {const angle = state.time * planet.speed;const planetX = centerX + Math.cos(angle) * planet.distance * state.zoom;const planetY = centerY + Math.sin(angle) * planet.distance * state.zoom * 0.5;// 应用旋转const rotatedX = centerX + (planetX - centerX) * Math.cos(state.rotationY) - (planetY - centerY) * Math.sin(state.rotationY);const rotatedY = centerY + (planetX - centerX) * Math.sin(state.rotationY) + (planetY - centerY) * Math.cos(state.rotationY);// 绘制轨道ctx.beginPath();ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)';ctx.ellipse(centerX, centerY, planet.distance * state.zoom, planet.distance * state.zoom * 0.5, 0, 0, Math.PI * 2);ctx.stroke();// 绘制行星ctx.save();ctx.translate(rotatedX, rotatedY);ctx.rotate(state.rotationX);// 如果是土星,绘制光环if (planet.name === "土星" && planet.rings) {ctx.beginPath();ctx.strokeStyle = 'rgba(210, 180, 140, 0.7)';ctx.lineWidth = 3;ctx.ellipse(0, 0, planet.rings.outer * scaleFactor * state.zoom, planet.rings.outer * scaleFactor * state.zoom * 0.3, 0, 0, Math.PI * 2);ctx.stroke();ctx.beginPath();ctx.strokeStyle = 'rgba(210, 180, 140, 0.4)';ctx.lineWidth = 5;ctx.ellipse(0, 0, planet.rings.inner * scaleFactor * state.zoom, planet.rings.inner * scaleFactor * state.zoom * 0.3, 0, 0, Math.PI * 2);ctx.stroke();}// 绘制行星主体const gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, planet.radius * scaleFactor * state.zoom);gradient.addColorStop(0, planet.color);gradient.addColorStop(1, darkenColor(planet.color, 0.5));ctx.beginPath();ctx.fillStyle = gradient;ctx.arc(0, 0, planet.radius * scaleFactor * state.zoom, 0, Math.PI * 2);ctx.fill();// 如果是选中的行星,添加高亮if (state.selectedPlanet === planet) {ctx.beginPath();ctx.strokeStyle = 'white';ctx.lineWidth = 2;ctx.arc(0, 0, planet.radius * scaleFactor * state.zoom + 5, 0, Math.PI * 2);ctx.stroke();}// 绘制卫星if (planet.moons) {planet.moons.forEach(moon => {const moonAngle = state.time * moon.speed;const moonX = Math.cos(moonAngle) * moon.distance * scaleFactor * state.zoom;const moonY = Math.sin(moonAngle) * moon.distance * scaleFactor * state.zoom * 0.5;ctx.beginPath();ctx.fillStyle = 'lightgray';ctx.arc(moonX, moonY, moon.radius * scaleFactor * state.zoom, 0, Math.PI * 2);ctx.fill();});}ctx.restore();});requestAnimationFrame(animate);}// 绘制星空背景function drawStars() {for (let i = 0; i < 500; i++) {if (!window.stars) {window.stars = Array(500).fill().map(() => ({x: Math.random() * canvas.width,y: Math.random() * canvas.height,size: Math.random() * 1.5,opacity: Math.random()}));}const star = window.stars[i];ctx.beginPath();ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity})`;ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);ctx.fill();}}// 颜色变暗函数function darkenColor(color, amount) {const num = parseInt(color.replace("#", ""), 16);let r = (num >> 16) * (1 - amount);let g = ((num >> 8) & 0xFFFF) * (1 - amount);let b = (num & 0xFFFF) * (1 - amount);return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;}// 窗口大小调整window.addEventListener('resize', () => {canvas.width = window.innerWidth;canvas.height = window.innerHeight;window.stars = null; // 重置星星位置});// 开始动画animate();</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年全国青少年信息素养大赛 scratch图形化编程挑战赛 小低组初赛 内部集训模拟题解析

2025年信息素养大赛初赛scratch模拟题解析 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 scratch资料 Scratch3.0系列视频课程资料零基础学习scratch3.0【入门教学 免费】零基础学习scratch3.0【视频教程 114节 免费】 历届蓝桥杯scratch国赛真题解析历届蓝桥杯scr…

grid网格布局

使用flex布局的痛点 如果使用justify-content: space-between;让子元素两端对齐&#xff0c;自动分配中间间距&#xff0c;假设一行4个&#xff0c;如果每一行都是4的倍数那没任何问题&#xff0c;但如果最后一行是2、3个的时候就会出现下面的状况&#xff1a; /* flex布局 两…

通义灵码2.5——基于MCP实现我的12306火车票智能查询小助手

本文因排版显示问题&#xff0c;为保证阅读体验&#xff0c;请大家访问&#xff1a; 通义灵码2.5——基于MCP打造我的12306火车票智能查询小助手-CSDN博客 前沿技术应用全景图 本项目作为通义灵码2.5的标杆实践案例&#xff0c;展现了AI辅助开发在复杂业务系统中的革命性突破…

Unity Button 交互动画

在UGUI的Button组件中&#xff0c;有一个过渡动画表现的功能。可以对按钮的不同交互状态添加交互反馈动画&#xff0c;来提高玩家的交互体验。 交互状态 名称 描述 Normal 正常情况 Highlighted 高亮显示&#xff0c;例如鼠标触碰到按钮点击范围 Pressed 按钮被按下的时…

钉钉热点实时推送助理-思路篇

以下是针对热点实时推送助理的功能描述&#xff0c;结合机器学习技术栈与用户场景的通俗化解释&#xff1a; 快速体验的话直接用钉钉扫描下方二维码体验 1. 核心功能 &#xff08;1&#xff09;热点抓取引擎 类比&#xff1a;像蜘蛛爬取全网信息&#xff08;网络爬虫信息抽取…

remote: error: hook declined to update refs/heads.....

gitee拉取分支&#xff0c;修改上传出现的问题&#xff0c;折腾了好久&#xff0c;浅浅记录. 1. 首次克隆仓库 # 克隆仓库&#xff08;使用 HTTPS 或 SSH&#xff09; git clone ------------ cd xxx-project2. 配置正确的用户信息&#xff08;关键步骤&#xff01;&#xff…

使用Vue + Element Plus实现可多行编辑的分页表格

需求背景&#xff1a; 在现代前端开发中&#xff0c;表格作为数据展示和交互的重要组件&#xff0c;在各类管理系统、数据平台中有着广泛的应用。随着用户对数据操作便捷性要求的不断提高&#xff0c;具备灵活编辑功能的表格成为了开发中的常见需求。特别是在需求处理大…

奥威BI+AI——高效智能数据分析工具,引领数据分析新时代

随着数据量的激增&#xff0c;企业对高效、智能的数据分析工具——奥威BIAI的需求日益迫切。奥威BIAI&#xff0c;作为一款颠覆性的数据分析工具&#xff0c;凭借其独特功能&#xff0c;正在引领数据分析领域的新纪元。 一、‌零报表环境下的极致体验‌ 奥威BIAI突破传统报表限…

【机器学习基础】机器学习入门核心算法:K均值(K-Means)

机器学习入门核心算法&#xff1a;K均值&#xff08;K-Means&#xff09; 1. 算法逻辑2. 算法原理与数学推导2.1 目标函数2.2 数学推导2.3 时间复杂度 3. 模型评估内部评估指标外部评估指标&#xff08;需真实标签&#xff09; 4. 应用案例4.1 客户细分4.2 图像压缩4.3 文档聚类…

springboot多模块父pom打包正常,单模块报错

背景&#xff1a;因为项目开发中经常发测试环境&#xff0c;发现使用阿里的插件能一键上传&#xff0c;不用手动上传比较方便。但是多模块有多个启动jar的时候&#xff0c;全局打包太慢&#xff0c;单独打发现报错。这里贴一下我使用这个插件的方式&#xff1a; 附带一个我感觉…

通义灵码2.5——基于MCP打造我的12306火车票智能查询小助手

前沿技术应用全景图 本项目作为通义灵码2.5的标杆实践案例&#xff0c;展现了AI辅助开发在复杂业务系统中的革命性突破。通过深度集成12306 MCP服务体系&#xff0c;我们构建了一个融合智能决策、环境感知和自主优化的新一代火车票查询系统。 #mermaid-svg-4D7QqwJjsQRdKVP7 {…

进程间通信(共享内存)

目录 前置&#xff1a; 一 原理 二 API 1. shmgetr 2. shmctl 3. 指令操作 2. 删除 3. 挂接 4. 断开挂接 三 demo代码 四 共享内存的特征 前置&#xff1a; 1.前面说的不管是匿名管道还是命名管道都是基于文件的思想构建的一套进程间通信的方案&#xff0c;那有没有…

详解GPU

详解GPU GPU&#xff08;图形处理器&#xff09;就像电脑里的 “图形小能手”&#xff0c;原本主要用来画画&#xff08;渲染图形&#xff09;&#xff0c;现在还能帮忙干很多杂活&#xff08;并行计算&#xff09; 一、先认识 GPU 的 “钥匙”&#xff1a;驱动和开发工具 装驱…

体育遇上AI:解读新一代智能阅读产品

在信息过载的今天&#xff0c;体育迷们时常面对这样的困扰&#xff1a;如何从海量赛事新闻、数据分析和深度评论中高效获取自己真正关心的内容&#xff1f;体育AI阅读产品正成为解决这一痛点的关键钥匙——它融合人工智能技术与体育内容生态&#xff0c;为球迷提供智能化、个性…

外网访问可视化工具 Grafana (Linux版本)

Grafana 是一款强大的可视化监控指标的展示工具&#xff0c;可以将不同的数据源数据以图形化的方式展示&#xff0c;不仅通用而且非常美观。它支持多种数据源&#xff0c;如 prometheus 等&#xff0c;也可以通过插件和 API 进行扩展以满足各种需求。 本文将详细介绍如何在本地…

Java开发经验——阿里巴巴编码规范实践解析4

摘要 本文主要介绍了阿里巴巴编码规范中关于日志处理的相关实践解析。强调了使用日志框架&#xff08;如 SLF4J、JCL&#xff09;而非直接使用日志系统&#xff08;如 Log4j、Logback&#xff09;的 API 的重要性&#xff0c;包括解耦日志实现、统一日志调用方式等好处。同时&…

各个链接集合

golang学习&#xff5e;&#xff5e;_从数组中取一个相同大小的slice有成本吗?-CSDN博客 框架 golang学习&#xff5e;&#xff5e;_从数组中取一个相同大小的slice有成本吗?-CSDN博客 golang k8s学习_容器化部署和传统部署区别-CSDN博客 K8S rabbitmq_rabbitmq 广播-CSD…

Cesium 展示——获取鼠标移动、点击位置的几种方法

文章目录 需求分析:这里我们用到了几种常见的鼠标事件1. 获取鼠标移动的位置2. 获取鼠标点击的位置3. 添加面4. 示例代码需求 获取指定断面的 label 分析:这里我们用到了几种常见的鼠标事件 1. 获取鼠标移动的位置 viewer.screenSpaceEventHandler.setInputAction((moveme…

技术分享 | Oracle SQL优化案例一则

本文为墨天轮数据库管理服务团队第70期技术分享&#xff0c;内容原创&#xff0c;作者为技术顾问马奕璇&#xff0c;如需转载请联系小墨&#xff08;VX&#xff1a;modb666&#xff09;并注明来源。 一、问题概述 开发人员反映有条跑批语句在测试环境执行了很久都没结束&…

$3 #12阶段三小结Java se

$3 #12 阶段三小结 Java se 基本没有新学什么知识点 感觉 基础语法 和高级语法 已经学完了 现在就是得学习 一些企业开发的框架 以及项目架构的思维 比如一个产品 从需求分析 到功能模块设计 到接口文档定义 数据库建立 前端接口页面设计 后端接口开发的步骤 然后现在比…