From dc318c04e3f784a1bf3e03a6cb084c68b84a7284 Mon Sep 17 00:00:00 2001 From: mini2024 Date: Wed, 5 Mar 2025 00:42:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20Cesium=20=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD=E5=92=8C=E9=85=8D=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A0=B7=E5=BC=8F=E5=8F=8A=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- eslint.config.ts | 2 + package.json | 3 + pnpm-lock.yaml | 273 ++++++++++++++++++ src/layouts/sakai-vue/styles/_main.scss | 1 + src/pages/cesium/README.md | 10 + .../cesium/cesium-helper/00.cesium-init.ts | 83 ++++++ src/pages/cesium/cesium-helper/01.x.ts | 118 ++++++++ src/pages/cesium/index.page.vue | 30 ++ typed-router.d.ts | 1 + vite.config.plugins.ts | 16 + vite.config.ts | 3 +- 12 files changed, 540 insertions(+), 3 deletions(-) create mode 100644 src/pages/cesium/README.md create mode 100644 src/pages/cesium/cesium-helper/00.cesium-init.ts create mode 100644 src/pages/cesium/cesium-helper/01.x.ts create mode 100644 src/pages/cesium/index.page.vue diff --git a/.vscode/settings.json b/.vscode/settings.json index 33c89a8..58b2816 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,6 +20,5 @@ "typescript.tsdk": "node_modules/typescript/lib", "typescript.preferences.autoImportFileExcludePatterns": ["vue-router/auto$"], "i18n-ally.localesPaths": ["src/locales"], - "i18n-ally.keystyle": "nested", - "oxc.enable": true + "i18n-ally.keystyle": "nested" } diff --git a/eslint.config.ts b/eslint.config.ts index fb99d32..2496aca 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -4,6 +4,7 @@ import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescri import pluginImport from 'eslint-plugin-import-x'; import oxlint from 'eslint-plugin-oxlint'; import perfectionist from 'eslint-plugin-perfectionist'; +import perfectionistPlugin from 'eslint-plugin-perfectionist'; import pluginVue from 'eslint-plugin-vue'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -68,6 +69,7 @@ export default defineConfigWithVueTs( }, // https://perfectionist.dev/guide/getting-started + perfectionistPlugin.configs['recommended-natural'], { plugins: { perfectionist, diff --git a/package.json b/package.json index 02e215a..1be1384 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "alova": "^3.2.8", "ant-design-vue": "~4.2.6", "axios": "^1.7.9", + "cesium": "^1.127.0", "consola": "^3.4.0", "dayjs": "^1.11.13", "deep-freeze-es6": "^4.0.0", @@ -63,6 +64,7 @@ "primelocale": "^2.0.0", "primevue": "^4.3.1", "radash": "^12.1.0", + "satellite.js": "^5.0.0", "tdesign-icons-vue-next": "^0.3.4", "ts-enum-util": "^4.1.0", "utils4u": "^4.0.0", @@ -124,6 +126,7 @@ "vite": "^6.1.0", "vite-plugin-cdn-import": "^1.0.1", "vite-plugin-fake-server": "^2.2.0", + "vite-plugin-static-copy": "^2.3.0", "vite-plugin-vue-devtools": "^7.7.1", "vite-plugin-vue-layouts": "^0.11.0", "vite-plugin-vue-meta-layouts": "^0.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac7fc20..93c911c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,6 +46,9 @@ importers: axios: specifier: ^1.7.9 version: 1.7.9 + cesium: + specifier: ^1.127.0 + version: 1.127.0 consola: specifier: ^3.4.0 version: 3.4.0 @@ -88,6 +91,9 @@ importers: radash: specifier: ^12.1.0 version: 12.1.0 + satellite.js: + specifier: ^5.0.0 + version: 5.0.0 tdesign-icons-vue-next: specifier: ^0.3.4 version: 0.3.4(vue@3.5.13(typescript@5.7.3)) @@ -266,6 +272,9 @@ importers: vite-plugin-fake-server: specifier: ^2.2.0 version: 2.2.0 + vite-plugin-static-copy: + specifier: ^2.3.0 + version: 2.3.0(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(less@4.2.2)(sass-embedded@1.83.4)(terser@5.38.2)(tsx@4.19.2)(yaml@2.7.0)) vite-plugin-vue-devtools: specifier: ^7.7.1 version: 7.7.1(@nuxt/kit@3.15.1(rollup@4.30.1))(rollup@4.30.1)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(less@4.2.2)(sass-embedded@1.83.4)(terser@5.38.2)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) @@ -480,6 +489,14 @@ packages: '@bufbuild/protobuf@2.2.3': resolution: {integrity: sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==} + '@cesium/engine@15.0.0': + resolution: {integrity: sha512-jimj7khIf/mBkejsMZ+n6Y9PPvXh4QmWKkz2ekFz59icDCeGj8ZJrzl5p0caqiK/372mnHOwmYFWYEwThEw2ew==} + engines: {node: '>=14.0.0'} + + '@cesium/widgets@11.0.0': + resolution: {integrity: sha512-4ELgFuU2uwkvD6NI9MHIWNFKjmyI9wlDzZ9NuoPFSnUhf9XfVBI8sJekGx5dijxjK2S3aCuxB3dtUkdDZEsQmA==} + engines: {node: '>=14.0.0'} + '@commitlint/config-validator@19.5.0': resolution: {integrity: sha512-CHtj92H5rdhKt17RmgALhfQt95VayrUo2tSqY9g2w+laAXyk7K/Ef6uPm9tn5qSIwSmrLjKaXK9eiNuxmQrDBw==} engines: {node: '>=v18'} @@ -1210,6 +1227,36 @@ packages: resolution: {integrity: sha512-AOnbzzYr0Y7w7M1jTypNQQyDtEbrzjCmjnFf8tQ72fAHpTU2+W7O7aw0oO17VCh5TLyZkCftwWG9N6SfCv3o+Q==} engines: {node: '>=12.11.0'} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@rollup/pluginutils@5.1.4': resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} @@ -1353,6 +1400,9 @@ packages: '@tsconfig/node22@22.0.0': resolution: {integrity: sha512-twLQ77zevtxobBOD4ToAtVmuYrpeYUh3qh+TEp+08IWhpsrIflVHqQ1F1CiPxQGL7doCdBIOOCF+1Tm833faNg==} + '@tweenjs/tween.js@25.0.0': + resolution: {integrity: sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -1395,6 +1445,9 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} @@ -1979,6 +2032,10 @@ packages: '@vueuse/shared@12.5.0': resolution: {integrity: sha512-vMpcL1lStUU6O+kdj6YdHDixh0odjPAUM15uJ9f7MY781jcYkIwFA4iv2EfoIPO6vBmvutI1HxxAwmf0cx5ISQ==} + '@zip.js/zip.js@2.7.57': + resolution: {integrity: sha512-BtonQ1/jDnGiMed6OkV6rZYW78gLmLswkHOzyMrMb+CAR7CZO8phOHO6c2qw6qb1g1betN7kwEHhhZk30dv+NA==} + engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=16.5.0'} + abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -2132,6 +2189,9 @@ packages: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} + autolinker@4.1.0: + resolution: {integrity: sha512-mYzdZMei1zIXcHVS/LjnuCJG+C/hNi8O+5m0R8YWtrIBWGrjL8CVzEZXxOfH0l1kioEXHNpUJRkgZdyL4GgIHQ==} + aws-sign2@0.7.0: resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} @@ -2166,6 +2226,9 @@ packages: birpc@0.2.19: resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} + bitmap-sdf@1.0.4: + resolution: {integrity: sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -2259,6 +2322,10 @@ packages: caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + cesium@1.127.0: + resolution: {integrity: sha512-MRGkPb3ClEkAI9viZxxdD3LCu7ydOzOKdJ6/iPtBx1GUsPCZNbgB0IH7wmhwgbxA5sjv4/a90+mvR9CoLP1PWQ==} + engines: {node: '>=18.18.0'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2597,13 +2664,22 @@ packages: dom-scroll-into-view@2.0.1: resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==} + dompurify@3.2.4: + resolution: {integrity: sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==} + dotenv@16.4.7: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} + draco3d@1.5.7: + resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + earcut@3.0.1: + resolution: {integrity: sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -3201,6 +3277,9 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -3501,6 +3580,10 @@ packages: jsencrypt@3.3.2: resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==} + jsep@1.4.0: + resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} + engines: {node: '>= 10.16.0'} + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -3553,6 +3636,9 @@ packages: resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} engines: {node: '>=0.6.0'} + kdbush@4.0.2: + resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -3577,6 +3663,12 @@ packages: kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + ktx-parse@1.0.0: + resolution: {integrity: sha512-Z31kVizz4DF/6vo9YiSYVBhuXAfyQy9bGxlW3+mB5OELoZjfXVZQpRoctsx8IEDKxBd6SagXKo7qRvu38i8Jfg==} + + lerc@2.0.0: + resolution: {integrity: sha512-7qo1Mq8ZNmaR4USHHm615nEW2lPeeWJ3bTyoqFbd35DLx0LUH7C6ptt5FDCTAlbIzs3+WKrk5SkJvw8AFDE2hg==} + less@4.2.2: resolution: {integrity: sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==} engines: {node: '>=6'} @@ -3650,6 +3742,9 @@ packages: resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} + long@5.3.1: + resolution: {integrity: sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==} + longest@2.0.1: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'} @@ -3715,6 +3810,12 @@ packages: merge@2.1.1: resolution: {integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==} + mersenne-twister@1.1.0: + resolution: {integrity: sha512-mUYWsMKNrm4lfygPkL3OfGzOPTR2DBlTkBNHM//F6hGp8cLThY897crAlk3/Jo17LEOOjQUrNAx6DvgO77QJkA==} + + meshoptimizer@0.22.0: + resolution: {integrity: sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg==} + micro@9.3.5-canary.3: resolution: {integrity: sha512-viYIo9PefV+w9dvoIBh1gI44Mvx1BOk67B4BpC2QK77qdY0xZF0Q+vWLt/BII6cLkIc8rLmSIcJaB/OrXXKe1g==} engines: {node: '>= 8.0.0'} @@ -3935,6 +4036,9 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + nosleep.js@0.12.0: + resolution: {integrity: sha512-9d1HbpKLh3sdWlhXMhU6MMH+wQzKkrgfRkYV0EBdvt99YJfj0ilCJrWRDYG2130Tm4GXbEoTCx5b34JSaP+HhA==} + npm-normalize-package-bin@4.0.0: resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} engines: {node: ^18.17.0 || >=20.5.0} @@ -4030,6 +4134,10 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@7.0.3: + resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + engines: {node: '>=18'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -4048,6 +4156,9 @@ packages: vue: ^3.0.0 vue-router: ^4.0.0 + pako@2.1.0: + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -4260,6 +4371,10 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -4284,6 +4399,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quickselect@2.0.0: + resolution: {integrity: sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==} + radash@12.1.0: resolution: {integrity: sha512-b0Zcf09AhqKS83btmUeYBS8tFK7XL2e3RvLmZcm0sTdF1/UUlHSsjXdCcWNxe7yfmAlPve5ym0DmKGtTzP6kVQ==} engines: {node: '>=14.18.0'} @@ -4295,6 +4413,9 @@ packages: resolution: {integrity: sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==} engines: {node: '>= 0.8'} + rbush@3.0.1: + resolution: {integrity: sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==} + rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} @@ -4539,6 +4660,9 @@ packages: engines: {node: '>=16.0.0'} hasBin: true + satellite.js@5.0.0: + resolution: {integrity: sha512-ie3yiJ2LJAJIhVUKdYhgp7V0btXKAMImDjRnuaNfJGl8rjwP2HwVIh4HLFcpiXYEiYwXc5fqh5+yZqCe6KIwWw==} + sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} @@ -4840,6 +4964,10 @@ packages: resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} engines: {node: '>=0.6'} + topojson-client@3.1.0: + resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==} + hasBin: true + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -5133,6 +5261,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + urijs@1.19.11: + resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} + url-parse-as-address@1.0.0: resolution: {integrity: sha512-1WJ8YX1Kcec9wgxy8d/ATzGP1ayO6BRnd3iB6NlM+7cOnn6U8p5PKppRTCPLobh3CSdJ4d0TdPjopzyU2KcVFw==} @@ -5225,6 +5356,12 @@ packages: '@nuxt/kit': optional: true + vite-plugin-static-copy@2.3.0: + resolution: {integrity: sha512-LLKwhhHetGaCnWz4mas4qqjjguDka6/6b4+SeIohRroj8aCE7QTfiZECfPecslFQkWZ3HdQuq5kOPmWZjNYlKA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^6.1.0 + vite-plugin-vue-devtools@7.7.1: resolution: {integrity: sha512-f1Fnda4CJYH7t7K1WaTEjFTLdF4oUkmlZTVwBGG5UhJ+Oa5KPX0Ue32c+YWRMOpCtFbCDl1iXGgQVzg8Ew5JnQ==} engines: {node: '>=v14.21.3'} @@ -5733,6 +5870,33 @@ snapshots: '@bufbuild/protobuf@2.2.3': {} + '@cesium/engine@15.0.0': + dependencies: + '@tweenjs/tween.js': 25.0.0 + '@zip.js/zip.js': 2.7.57 + autolinker: 4.1.0 + bitmap-sdf: 1.0.4 + dompurify: 3.2.4 + draco3d: 1.5.7 + earcut: 3.0.1 + grapheme-splitter: 1.0.4 + jsep: 1.4.0 + kdbush: 4.0.2 + ktx-parse: 1.0.0 + lerc: 2.0.0 + mersenne-twister: 1.1.0 + meshoptimizer: 0.22.0 + pako: 2.1.0 + protobufjs: 7.4.0 + rbush: 3.0.1 + topojson-client: 3.1.0 + urijs: 1.19.11 + + '@cesium/widgets@11.0.0': + dependencies: + '@cesium/engine': 15.0.0 + nosleep.js: 0.12.0 + '@commitlint/config-validator@19.5.0': dependencies: '@commitlint/types': 19.5.0 @@ -6350,6 +6514,29 @@ snapshots: '@primevue/metadata@4.3.1': {} + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@rollup/pluginutils@5.1.4(rollup@4.30.1)': dependencies: '@types/estree': 1.0.6 @@ -6447,6 +6634,8 @@ snapshots: '@tsconfig/node22@22.0.0': {} + '@tweenjs/tween.js@25.0.0': {} + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 @@ -6486,6 +6675,9 @@ snapshots: '@types/parse-json@4.0.2': {} + '@types/trusted-types@2.0.7': + optional: true + '@types/web-bluetooth@0.0.20': {} '@typescript-eslint/eslint-plugin@8.20.0(@typescript-eslint/parser@8.20.0(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': @@ -7446,6 +7638,8 @@ snapshots: transitivePeerDependencies: - typescript + '@zip.js/zip.js@2.7.57': {} + abbrev@2.0.0: {} acorn-import-attributes@1.9.5(acorn@8.14.0): @@ -7598,6 +7792,10 @@ snapshots: at-least-node@1.0.0: {} + autolinker@4.1.0: + dependencies: + tslib: 2.8.1 + aws-sign2@0.7.0: {} aws4@1.13.2: {} @@ -7638,6 +7836,8 @@ snapshots: birpc@0.2.19: {} + bitmap-sdf@1.0.4: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -7736,6 +7936,11 @@ snapshots: caseless@0.12.0: {} + cesium@1.127.0: + dependencies: + '@cesium/engine': 15.0.0 + '@cesium/widgets': 11.0.0 + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -8066,10 +8271,18 @@ snapshots: dom-scroll-into-view@2.0.1: {} + dompurify@3.2.4: + optionalDependencies: + '@types/trusted-types': 2.0.7 + dotenv@16.4.7: {} + draco3d@1.5.7: {} + duplexer@0.1.2: {} + earcut@3.0.1: {} + eastasianwidth@0.2.0: {} ecc-jsbn@0.1.2: @@ -8757,6 +8970,8 @@ snapshots: graceful-fs@4.2.11: {} + grapheme-splitter@1.0.4: {} + graphemer@1.4.0: {} gray-matter@4.0.3: @@ -9019,6 +9234,8 @@ snapshots: jsencrypt@3.3.2: {} + jsep@1.4.0: {} + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -9066,6 +9283,8 @@ snapshots: json-schema: 0.4.0 verror: 1.10.0 + kdbush@4.0.2: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -9084,6 +9303,10 @@ snapshots: kolorist@1.8.0: {} + ktx-parse@1.0.0: {} + + lerc@2.0.0: {} + less@4.2.2: dependencies: copy-anything: 2.0.6 @@ -9181,6 +9404,8 @@ snapshots: strip-ansi: 7.1.0 wrap-ansi: 9.0.0 + long@5.3.1: {} + longest@2.0.1: {} loose-envify@1.4.0: @@ -9245,6 +9470,10 @@ snapshots: merge@2.1.1: {} + mersenne-twister@1.1.0: {} + + meshoptimizer@0.22.0: {} + micro@9.3.5-canary.3: dependencies: arg: 4.1.0 @@ -9418,6 +9647,8 @@ snapshots: normalize-path@3.0.0: {} + nosleep.js@0.12.0: {} + npm-normalize-package-bin@4.0.0: {} npm-run-all2@7.0.2: @@ -9552,6 +9783,8 @@ snapshots: dependencies: p-limit: 3.1.0 + p-map@7.0.3: {} + package-json-from-dist@1.0.1: {} package-manager-detector@0.2.8: {} @@ -9565,6 +9798,8 @@ snapshots: vue: 3.5.13(typescript@5.7.3) vue-router: 4.5.0(vue@3.5.13(typescript@5.7.3)) + pako@2.1.0: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -9743,6 +9978,21 @@ snapshots: proto-list@1.2.4: {} + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 22.13.1 + long: 5.3.1 + proxy-from-env@1.1.0: {} prr@1.0.1: @@ -9760,6 +10010,8 @@ snapshots: queue-microtask@1.2.3: {} + quickselect@2.0.0: {} + radash@12.1.0: {} rate-limiter-flexible@5.0.4: {} @@ -9771,6 +10023,10 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + rbush@3.0.1: + dependencies: + quickselect: 2.0.0 + rc9@2.1.2: dependencies: defu: 6.1.4 @@ -10010,6 +10266,8 @@ snapshots: sass-embedded-win32-ia32: 1.83.4 sass-embedded-win32-x64: 1.83.4 + satellite.js@5.0.0: {} + sax@1.4.1: optional: true @@ -10337,6 +10595,10 @@ snapshots: toidentifier@1.0.0: {} + topojson-client@3.1.0: + dependencies: + commander: 2.20.3 + totalist@3.0.1: {} tough-cookie@2.5.0: @@ -10721,6 +10983,8 @@ snapshots: dependencies: punycode: 2.3.1 + urijs@1.19.11: {} + url-parse-as-address@1.0.0: {} util-deprecate@1.0.2: {} @@ -10823,6 +11087,15 @@ snapshots: - rollup - supports-color + vite-plugin-static-copy@2.3.0(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(less@4.2.2)(sass-embedded@1.83.4)(terser@5.38.2)(tsx@4.19.2)(yaml@2.7.0)): + dependencies: + chokidar: 3.6.0 + fast-glob: 3.3.3 + fs-extra: 11.2.0 + p-map: 7.0.3 + picocolors: 1.1.1 + vite: 6.1.0(@types/node@22.13.1)(jiti@2.4.2)(less@4.2.2)(sass-embedded@1.83.4)(terser@5.38.2)(tsx@4.19.2)(yaml@2.7.0) + vite-plugin-vue-devtools@7.7.1(@nuxt/kit@3.15.1(rollup@4.30.1))(rollup@4.30.1)(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(less@4.2.2)(sass-embedded@1.83.4)(terser@5.38.2)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)): dependencies: '@vue/devtools-core': 7.7.1(vite@6.1.0(@types/node@22.13.1)(jiti@2.4.2)(less@4.2.2)(sass-embedded@1.83.4)(terser@5.38.2)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)) diff --git a/src/layouts/sakai-vue/styles/_main.scss b/src/layouts/sakai-vue/styles/_main.scss index e85dcb2..2fdbe06 100644 --- a/src/layouts/sakai-vue/styles/_main.scss +++ b/src/layouts/sakai-vue/styles/_main.scss @@ -13,4 +13,5 @@ .layout-main { flex: 1 1 auto; padding-bottom: 2rem; + position: relative; } diff --git a/src/pages/cesium/README.md b/src/pages/cesium/README.md new file mode 100644 index 0000000..aa2ffa9 --- /dev/null +++ b/src/pages/cesium/README.md @@ -0,0 +1,10 @@ +## 配置项目 +- https://github.dev/CesiumGS/cesium-vite-example +- https://cesium.com/blog/2024/02/13/configuring-vite-or-webpack-for-cesiumjs/ +- https://cesium.com/learn/cesiumjs-learn/cesiumjs-quickstart/ +- vite-plugin-cesium + +## 参考 +- https://www.npmjs.com/package/vue-cesium +- https://zouyaoji.top/vue-cesium/#/zh-CN/component/controls/vc-navigation +- https://cesium.pages.dev/ diff --git a/src/pages/cesium/cesium-helper/00.cesium-init.ts b/src/pages/cesium/cesium-helper/00.cesium-init.ts new file mode 100644 index 0000000..0eb2885 --- /dev/null +++ b/src/pages/cesium/cesium-helper/00.cesium-init.ts @@ -0,0 +1,83 @@ +import * as Cesium from 'cesium'; +import 'cesium/Build/Cesium/Widgets/widgets.css'; + +// Cesium.Ion.defaultAccessToken = +// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiYjZmMWM4Ny01YzQ4LTQ3MzUtYTI5Mi1hNTgyNjdhMmFiMmMiLCJpZCI6NjIwMjgsImlhdCI6MTYyNjY3MTMxNX0.5SelYUyzXWRoMyjjFvmFIAoPtWlJPQMjsVl2e_jQe-c'; + +export function cesium_init() { + // 复写原型方法 用于timeline组件日期格式化; + // @ts-expect-error node_modules/@cesium/widgets/Source/Timeline/Timeline.js + Cesium.Timeline.prototype.makeLabel = function (time) { + let minutes = 0 - new Date().getTimezoneOffset(); + let dataZone8 = Cesium.JulianDate.addMinutes(time, minutes, new Cesium.JulianDate()); + return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 19); + }; + + // cesium-viewer-bottom + + const viewer = new Cesium.Viewer('cesiumContainer', { + /* animationContainer: !true, */ + /* timelineContainer: true, */ + /* bottomContainer: document.createElement('p'), // The DOM element or ID that will contain the bottomContainer. If not specified, the bottomContainer is added to the widget itself. */ + shouldAnimate: true, + // globe: false, // 地球 + baseLayerPicker: true, + homeButton: true, // Home按钮 + fullscreenButton: !true, // 全屏按钮 + geocoder: true, // = IonGeocodeProviderType.DEFAULT] - 在使用Geocoder小部件进行搜索时使用的地理编码服务或服务。如果设置为false,则不会创建Geocoder小部件。 + infoBox: true, // InfoBox小部件。 + navigationHelpButton: !true, // 是否显示导航帮助按钮 + projectionPicker: !true, // 投影选择器 + sceneModePicker: true, // 是否显示场景模式选择器(2D/3D切换) + animation: true, // 是否创建动画小部件 + timeline: true, // If set to false, the Timeline widget will not be created. + selectionIndicator: true, + requestRenderMode: !true, // 如果为真,渲染帧将仅在场景内部发生变化时需要时发生。启用此功能可以减少应用程序的CPU/GPU使用率,并在移动设备上节省更多电量,但在此模式下需要使用{@link Scene#requestRender}显式渲染新帧。在API的其他部分对场景进行更改后,在许多情况下都需要这样做。请参阅{@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|使用显式渲染提高性能}。 + showRenderLoopErrors: true, // 如果为真,当发生渲染循环错误时,此小部件将自动向用户显示包含错误的HTML面板。 + orderIndependentTranslucency: false, // 顺序无关透明度 + shadows: true, // Determines if shadows are cast by light sources. + }); + /* if ($__DEV__) */ viewer.scene.debugShowFramesPerSecond = true; + + // 时间格式化 + let minutes = 0 - new Date().getTimezoneOffset(); // 0 - (-480); + viewer.animation.viewModel.timeFormatter = function (date, _viewModel) { + let dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate()); + return Cesium.JulianDate.toIso8601(dataZone8).slice(11, 19); + }; + viewer.animation.viewModel.dateFormatter = function (date, _viewModel) { + let dataZone8 = Cesium.JulianDate.addMinutes(date, minutes, new Cesium.JulianDate()); + return Cesium.JulianDate.toIso8601(dataZone8).slice(0, 10); + }; + + //高德卫星地图 + let gaoDeSatelliteImgLayer = new Cesium.UrlTemplateImageryProvider({ + url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', + minimumLevel: 3, + maximumLevel: 18, + tilingScheme: new Cesium.WebMercatorTilingScheme(), + }); + + const customLayerViewModel = new Cesium.ProviderViewModel({ + name: '高德地图', + iconUrl: 'gaodeImage.png', + tooltip: '高德地图', + category: 'Cesium ion', // 或 'Other 、Cesium ion'、'Bing Maps' 等 + creationFunction: function () { + return gaoDeSatelliteImgLayer; + }, + }); + // 设置高德地图为默认图层 + viewer.baseLayerPicker.viewModel.imageryProviderViewModels.unshift(customLayerViewModel); + const selectedViewModel = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[0]; + viewer.baseLayerPicker.viewModel.selectedImagery = selectedViewModel; + + Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees( + 75.0, // 西经 + 10.0, // 南纬 + 140.0, // 东经 + 60.0, // 北纬 + ); + + return viewer; +} diff --git a/src/pages/cesium/cesium-helper/01.x.ts b/src/pages/cesium/cesium-helper/01.x.ts new file mode 100644 index 0000000..5f0a1ae --- /dev/null +++ b/src/pages/cesium/cesium-helper/01.x.ts @@ -0,0 +1,118 @@ +import type { Viewer } from 'cesium'; +import * as Cesium from 'cesium'; +import { twoline2satrec, propagate, gstime, eciToEcf } from 'satellite.js'; + +export async function demoOrbitGeneration(viewer: Viewer) { + const tle = `STARLINK-11371 [DTC] +1 62879U 25024A 25062.93300820 .00003305 00000+0 21841-4 0 9995 +2 62879 42.9977 257.3937 0001725 269.2925 90.7748 15.77864921 5143`; + + // 解析TLE数据 + const lines = tle.split('\n'); + const satelliteName = lines[0].trim(); + const tleLine1 = lines[1]; + const tleLine2 = lines[2]; + + // 创建卫星记录 + const satrec = twoline2satrec(tleLine1, tleLine2); + + // 创建轨道点 + const pointsArray = []; + const totalMinutes = 1440; // 一天的分钟数 + const timeStepInMinutes = 10; + + // 当前时间 + const now = new Date(); + + // 计算一条完整的轨道 + for (let i = 0; i < totalMinutes; i += timeStepInMinutes) { + // 创建时间点 + const time = new Date(now.getTime() + i * 60000); + + // 获取卫星位置 + const positionAndVelocity = propagate(satrec, time); + + // 有时可能返回false + const position = positionAndVelocity.position; + if (typeof position === 'boolean') { + console.error('Error calculating satellite position'); + return; + } + // 转换为千米 + const gmst = gstime(time); + const p = eciToEcf(position, gmst); + + // 添加到点数组 + pointsArray.push( + Cesium.Cartesian3.fromDegrees( + Cesium.Math.toDegrees(Math.atan2(p.y, p.x)), + Cesium.Math.toDegrees(Math.atan2(p.z, Math.sqrt(p.x * p.x + p.y * p.y))), + Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z) * 1000, // 转换为米 + ), + ); + } + + // 获取当前位置用于放置卫星模型 + const time = new Date(); + const positionAndVelocity = propagate(satrec, time); + const position = positionAndVelocity.position; + const gmst = gstime(time); + if (typeof position === 'boolean') { + console.error('Error calculating satellite position'); + return; + } + const p = eciToEcf(position, gmst); + + const currentPosition = Cesium.Cartesian3.fromDegrees( + Cesium.Math.toDegrees(Math.atan2(p.y, p.x)), + Cesium.Math.toDegrees(Math.atan2(p.z, Math.sqrt(p.x * p.x + p.y * p.y))), + Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z) * 1000, // 转换为米 + ); + + // 创建轨道线 + const orbitPath = viewer.entities.add({ + name: `${satelliteName} Orbit`, + polyline: { + positions: pointsArray, + width: 2, + material: new Cesium.PolylineGlowMaterialProperty({ + glowPower: 0.2, + color: Cesium.Color.BLUE, + }), + }, + }); + + // 添加卫星实体 + const satellite = viewer.entities.add({ + name: satelliteName, + position: currentPosition, + point: { + pixelSize: 10, + color: Cesium.Color.YELLOW, + outlineColor: Cesium.Color.WHITE, + outlineWidth: 2, + }, + label: { + text: satelliteName, + font: '14pt sans-serif', + style: Cesium.LabelStyle.FILL_AND_OUTLINE, + fillColor: Cesium.Color.WHITE, + outlineColor: Cesium.Color.BLACK, + outlineWidth: 2, + verticalOrigin: Cesium.VerticalOrigin.BOTTOM, + pixelOffset: new Cesium.Cartesian2(0, -10), + }, + // billboard: { + // image: '/assets/satellite.png', // 您需要添加一个卫星图标 + // scale: 0.5, + // }, + }); + + // 将相机定位到卫星 + viewer.flyTo(satellite, { duration: 3 }); + + return { + orbitPath, + satellite, + }; +} diff --git a/src/pages/cesium/index.page.vue b/src/pages/cesium/index.page.vue new file mode 100644 index 0000000..4300628 --- /dev/null +++ b/src/pages/cesium/index.page.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/typed-router.d.ts b/typed-router.d.ts index 7d0bfa9..830cded 100644 --- a/typed-router.d.ts +++ b/typed-router.d.ts @@ -22,6 +22,7 @@ declare module 'vue-router/auto-routes' { '$Path': RouteRecordInfo<'$Path', '/:path(.*)', { path: ParamValue }, { path: ParamValue }>, 'AntdV': RouteRecordInfo<'AntdV', '/AntdV', Record, Record>, 'API': RouteRecordInfo<'API', '/API', Record, Record>, + 'Cesium': RouteRecordInfo<'Cesium', '/cesium', Record, Record>, 'DataLoadersId': RouteRecordInfo<'DataLoadersId', '/data-loaders/:id', { id: ParamValue }, { id: ParamValue }>, 'DataLoadersIdSub1UserId': RouteRecordInfo<'DataLoadersIdSub1UserId', '/data-loaders/:id/sub-1/:userId', { id: ParamValue, userId: ParamValue }, { id: ParamValue, userId: ParamValue }>, 'Fonts': RouteRecordInfo<'Fonts', '/fonts', Record, Record>, diff --git a/vite.config.plugins.ts b/vite.config.plugins.ts index 0388cbd..07f3eea 100644 --- a/vite.config.plugins.ts +++ b/vite.config.plugins.ts @@ -2,6 +2,8 @@ * https://github.com/antfu-collective/vitesse/blob/47618e72dfba76c77b9b85b94784d739e35c492b/vite.config.ts * https://github.com/vue-macros/vue-macros/blob/main/playground/vue3/vite.config.ts */ + +import { viteStaticCopy } from 'vite-plugin-static-copy'; import VueI18n from '@intlify/unplugin-vue-i18n/vite'; import { PrimeVueResolver } from '@primevue/auto-import-resolver'; import { unheadVueComposablesImports } from '@unhead/vue'; @@ -29,6 +31,11 @@ import Layouts from 'vite-plugin-vue-layouts'; import MetaLayouts from 'vite-plugin-vue-meta-layouts'; import { ViteWebfontDownload as WebfontDownload } from 'vite-plugin-webfont-dl'; +const cesiumSource = 'node_modules/cesium/Build/Cesium'; +// This is the base url for static files that CesiumJS needs to load. +// Set to an empty string to place the files at the site's root path +export const cesiumBaseUrl = 'cesiumStatic'; + export function Plugins() { const plugins: PluginOption[] = []; @@ -163,6 +170,15 @@ export function Plugins() { basename: 'fake-api', enableProd: true, }), + + viteStaticCopy({ + targets: [ + { dest: cesiumBaseUrl, src: `${cesiumSource}/ThirdParty` }, + { dest: cesiumBaseUrl, src: `${cesiumSource}/Workers` }, + { dest: cesiumBaseUrl, src: `${cesiumSource}/Assets` }, + { dest: cesiumBaseUrl, src: `${cesiumSource}/Widgets` }, + ], + }), ); const _unused = () => { diff --git a/vite.config.ts b/vite.config.ts index 6d3dfd8..0c27c46 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,7 +4,7 @@ import { fileURLToPath, URL } from 'node:url'; import { createViteProxy } from 'utils4u/vite'; import { defineConfig, loadEnv } from 'vite'; -import { Plugins } from './vite.config.plugins'; +import { cesiumBaseUrl, Plugins } from './vite.config.plugins'; // https://vitejs.dev/config/ export default defineConfig(({ mode, command }) => { @@ -16,6 +16,7 @@ export default defineConfig(({ mode, command }) => { plugins: Plugins(), define: { $__DEV__: JSON.stringify(!isBuild), + CESIUM_BASE_URL: JSON.stringify(`/${cesiumBaseUrl}`), }, resolve: { alias: {