@jjlmoya/utils-science 1.34.0 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +3 -1
- package/src/index.ts +1 -0
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/roche-limit-satellite-disruption/bibliography.astro +14 -0
- package/src/tool/roche-limit-satellite-disruption/bibliography.ts +16 -0
- package/src/tool/roche-limit-satellite-disruption/component.astro +97 -0
- package/src/tool/roche-limit-satellite-disruption/entry.ts +28 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/de.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/en.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/es.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/fr.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/id.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/it.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/ja.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/ko.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/nl.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/pl.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/pt.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/ru.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/sv.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/tr.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/i18n/zh.ts +229 -0
- package/src/tool/roche-limit-satellite-disruption/index.ts +11 -0
- package/src/tool/roche-limit-satellite-disruption/logic.ts +102 -0
- package/src/tool/roche-limit-satellite-disruption/particle-system.ts +66 -0
- package/src/tool/roche-limit-satellite-disruption/roche-limit-satellite-disruption-calculator.css +568 -0
- package/src/tool/roche-limit-satellite-disruption/script.ts +274 -0
- package/src/tool/roche-limit-satellite-disruption/seo.astro +15 -0
- package/src/tool/roche-limit-satellite-disruption/storage.ts +28 -0
- package/src/tool/roche-limit-satellite-disruption/visual-data.ts +16 -0
- package/src/tools.ts +2 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
const slug = 'roche-siniri-uydu-parcalanmasi-hesaplama';
|
|
2
|
+
const title = 'Roche Siniri Hesaplayici ve Uydu Parcalanma Simulatoru';
|
|
3
|
+
const description = 'Gezegenler ve uydular icin Roche sinirini hesaplayin, akiskan ve katI kirilma mesafelerini karsilastirin ve gelgit kuvvetlerinin bir uyduyu nasil bir halka sistemine donusturdugunu gorsellestirin.';
|
|
4
|
+
|
|
5
|
+
const howTo = [
|
|
6
|
+
{
|
|
7
|
+
name: 'Ana gok cismini secin',
|
|
8
|
+
text: 'Uyduyu ceken gezegeni secin. Hesaplayici, Roche siniri ve yorunge periyodu tahminleri icin yaricap, yogunluk ve kutle bilgilerini yukler.',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
name: 'Uydu turunu secin',
|
|
12
|
+
text: 'Bir buzlu uydu, kayali uydu, moloz yigini veya demirce zengin bir cisim secin. Yogunluk ve ic kohezyon, kirilma sinirini degistirir.',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'Yorunge kaydiricisini hareket ettirin',
|
|
16
|
+
text: 'Yorunge mesafesini ice veya disa surukleyin. Gorsel disk, uydunun Roche sinirinin disinda, ona dokunarak, parcalanarak veya bir halkaya donuserek olup olmadigini gosterir.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'Sinirlari karsilastirin',
|
|
20
|
+
text: 'Gostergeleri kullanarak klasik akiskan Roche sinirini, daha dusuk olan kati cisim tahminini ve kohezyona gore ayarlanmis calisma sinirini karsilastirin.',
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const faq = [
|
|
25
|
+
{
|
|
26
|
+
question: 'Roche siniri nedir?',
|
|
27
|
+
answer: 'Roche siniri, buyuk bir ana cismin gelgit kuvvetlerinin, daha kucuk bir yorunge cismi uzerinde, o cismin kendi kutle cekimini asacak kadar guclu hale geldigi mesafedir. Bu sinirin icinde, zayif veya akiskan bir uydu parcalanabilir.',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
question: 'Neden akiskan ve kati Roche sinirlari var?',
|
|
31
|
+
answer: 'Akiskan bir uydu kolayca deforme olur, bu nedenle gelgitler uzamasini artirabilir ve onu gezegenden daha uzakta parcalayabilir. Kati bir uydu, malzeme dayanimi ile deformasyona direnebilir, bu nedenle basit kati tahmini, kirilmayi ana cisme daha yakin bir yere koyar.',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
question: 'Roche sinirinin icindeki her ay aninda halkaya donusur mu?',
|
|
35
|
+
answer: 'Hayir. Gercek parcalanma; donus, bilesim, catlaklar, gozeneklilik, isinma, carpma ve malzeme dayanimina baglidir. Bu arac, klasik kutle cekim sinirini gosterir ve anlik bir gecis yerine bir gecis bolgesi kullanarak riski iletir.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
question: 'Saturn\'un halkalari neden Roche siniri fizigine yakin duruyor?',
|
|
39
|
+
answer: 'Saturn\'un halkalari, buzlu malzemenin tek bir buyuk ay haline gelmek yerine parcaciklar olarak kalabildigi bir bolgede bulunur. Roche siniri, halka parcaciklarinin neden gezegene yakin bir sekilde dagilmis halde kaldigini aciklamaya yardimci olur.',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
import { bibliography } from '../bibliography';
|
|
44
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
45
|
+
|
|
46
|
+
export const content: ToolLocaleContent = {
|
|
47
|
+
slug,
|
|
48
|
+
title,
|
|
49
|
+
description,
|
|
50
|
+
ui: {
|
|
51
|
+
primaryBody: 'Ana gok cismi',
|
|
52
|
+
satelliteType: 'Uydu turu',
|
|
53
|
+
orbitDistance: 'Yorunge mesafesi',
|
|
54
|
+
rocheBoundary: 'Roche siniri',
|
|
55
|
+
fluidLimit: 'Akiskan limit',
|
|
56
|
+
rigidLimit: 'Kati limit',
|
|
57
|
+
activeLimit: 'Aktif limit',
|
|
58
|
+
safetyRatio: 'Guvenlik orani',
|
|
59
|
+
orbitalPeriod: 'Yorunge periyodu',
|
|
60
|
+
tidalStress: 'Gelgit gerilimi',
|
|
61
|
+
ringFormation: 'Halka olusumu',
|
|
62
|
+
stable: 'Kararli yorunge',
|
|
63
|
+
grazing: 'Gelgit temasi',
|
|
64
|
+
fragmenting: 'Parcalaniyor',
|
|
65
|
+
ring: 'Halka sistemi',
|
|
66
|
+
km: 'km',
|
|
67
|
+
hours: 's',
|
|
68
|
+
density: 'Yogunluk',
|
|
69
|
+
cohesion: 'Kohezyon',
|
|
70
|
+
planetRadius: 'Gezegen yaricapi',
|
|
71
|
+
reset: 'Sifirla',
|
|
72
|
+
closePass: 'Yakin gecis',
|
|
73
|
+
moonTrack: 'Ay izi',
|
|
74
|
+
debrisTrack: 'Enkaz izi',
|
|
75
|
+
},
|
|
76
|
+
seo: [
|
|
77
|
+
{
|
|
78
|
+
type: 'title',
|
|
79
|
+
text: 'Roche Siniri Formulu, Anlami ve Bu Hesaplayici Nasil Kullanilir',
|
|
80
|
+
level: 2,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: 'paragraph',
|
|
84
|
+
html: '<strong>Roche siniri</strong>, temel olarak kendi kutle cekimiyle bir arada duran bir uydunun, gelgit kuvvetleri tarafindan parcalanmadan daha buyuk bir cismin yorungesinde dolanabilecegi minimum mesafedir. Insanlar genellikle bir ayin, kuyruklu yildizin, asteroitin veya yapay bir senaryonun bir gezegene yakin gecisinde hayatta kalip kalamayacagini veya malzemenin bir halkaya yayilip yayilmayacagini ogrenmek icin bu kavrami ararlar. Bu hesaplayici, gezegen yaricapi, gezegen yogunlugu, uydu yogunlugu ve uydunun yaklasik ic dayanimini bir araya getirerek bu soruyu yanitlar.',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: 'paragraph',
|
|
88
|
+
html: 'Temel fikir basittir: kutle cekimi uydu boyunca esit gucte degildir. Ana cisme yakin taraf, uzak taraftan daha fazla cekilir ve bir germe kuvveti olusturur. Bu gelgit germesi, uydunun kendi kutle cekiminden ve malzeme kohezyonundan daha gucluyse, cisim catlayabilir, kutle kaybedebilir ve sonunda parcalanabilir. Bu nedenle Roche siniri sadece bir mesafe degildir; dis gelgit gerilimi ile ic baglanma arasinda bir karsilastirmadir.',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
type: 'title',
|
|
92
|
+
text: 'Hesaplayici Tarafindan Kullanilan Roche Siniri Denklemleri',
|
|
93
|
+
level: 3,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'paragraph',
|
|
97
|
+
html: 'Akiskan veya cok zayif bir uydu icin klasik yaklasik deger <strong>d = 2.44 R (rho_M / rho_m)^(1/3)</strong> seklindedir. Kati bir uydu icin yaygin bir yaklasik deger <strong>d = 1.26 R (rho_M / rho_m)^(1/3)</strong> seklindedir. Bu denklemlerde <strong>d</strong>, gezegenin merkezinden olculen Roche siniri, <strong>R</strong> ana cismin yaricapi, <strong>rho_M</strong> ana cismin yogunlugu ve <strong>rho_m</strong> uydunun yogunlugudur.',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'list',
|
|
101
|
+
items: [
|
|
102
|
+
'<strong>Ana yaricap:</strong> Buyuk gezegenler, yogunluk benzer olsa bile daha buyuk bir Roche siniri mesafesi olusturur.',
|
|
103
|
+
'<strong>Ana yogunluk:</strong> Yogun bir ana cisim, yaricapinin belirli bir katinda gelgit kuvvetini artirir.',
|
|
104
|
+
'<strong>Uydu yogunlugu:</strong> Yogun bir uydunun kendi kutle cekimi daha gucludur, bu nedenle gezegene daha yakin hayatta kalabilir.',
|
|
105
|
+
'<strong>Uydu dayanimi:</strong> Akiskan, buzlu, catlakli veya moloz yigini bir cisim, kompakt bir kati cisimden daha uzakta parcalanir.',
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'table',
|
|
110
|
+
headers: ['Model', 'Formul sekli', 'Kullanim alani', 'Sonucun anlami'],
|
|
111
|
+
rows: [
|
|
112
|
+
['Akiskan Roche siniri', '2.44 R (rho_M / rho_m)^(1/3)', 'Buzlu uydular, erimis cisimler, moloz yiginlari, zayif kuyruklu yildizlar', 'Kolay deforme olan cisimler icin ihtiyatli kirilma mesafesi.'],
|
|
113
|
+
['Kati Roche siniri', '1.26 R (rho_M / rho_m)^(1/3)', 'Malzeme dayanimina sahip yogun kayali veya metalik cisimler', 'Malzeme dayaniminin parcalanmayi geciktirdigi daha yakin bir alt sinir.'],
|
|
114
|
+
['Kohezyona gore ayarli gosterim', 'Akiskan ve kati durum arasinda', 'Bu simulatorde hizli senaryo karsilastirmasi', 'Secilen uydu turu icin pratik bir risk cizgisi, evrensel bir doga yasasi degil.'],
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'title',
|
|
119
|
+
text: 'Ornek: Buzlu Bir Ay Neden Saturn Yakininda Savunmasizdir',
|
|
120
|
+
level: 3,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'paragraph',
|
|
124
|
+
html: 'Saturn, Dunya\'dan cok daha az yogundur, ancak cok buyuktur. Dusuk yogunluklu bir buzlu uydunun kendi kutle cekimi, kompakt bir kayali aya kiyasla zayiftir, bu nedenle yogunluk orani akiskan Roche sinirini Saturn\'un bulut tepelerinden hala uzaga yerlestirir. Roche siniri fiziginin, Saturn\'un neden buyuk bir yeniden birlesmis ay yerine cogunlukla buzlu parcaciklardan olusan genis ve parlak bir halka sistemini koruyabildigini anlamanin merkezinde olmasinin nedenlerinden biri budur.',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'paragraph',
|
|
128
|
+
html: 'Hesaplayicida Saturn ve bir buzlu ay secip yorungeyi ice suruklerseniz guvenlik oranini izleyin. <strong>1.00x</strong> degerinin uzerinde, secilen yorunge aktif Roche sinirinin disindadir. <strong>1.00x</strong> degerine yakin, ay, kutle kaybi veya catlamanin olasi oldugu bir gelgit temas bolgesindedir. <strong>1.00x</strong> degerinin altinda, gorsellestirme parca yaylarina ve halka olusumuna dogru kayar, cunku secilen model parcalanmayi ongorur.',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: 'title',
|
|
132
|
+
text: 'Guvenlik Orani Nasil Yorumlanir',
|
|
133
|
+
level: 3,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
type: 'paragraph',
|
|
137
|
+
html: '<strong>Guvenlik orani</strong>, mevcut yorunge mesafesinin secilen Roche sinirina bolunmesidir. <strong>1.25x</strong> orani, yorungenin aktif kirilma tahmininden %25 daha uzakta oldugu anlamina gelir. <strong>1.00x</strong> orani, yorungenin tam olarak secilen Roche sinirinda oldugu anlamina gelir. <strong>0.80x</strong> orani, uydunun secilen parcalanma bolgesinin oldukca icinde oldugu anlamina gelir.',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: 'table',
|
|
141
|
+
headers: ['Guvenlik orani', 'Goruntulenen durum', 'Pratik anlami'],
|
|
142
|
+
rows: [
|
|
143
|
+
['1.12x uzeri', 'Kararli yorunge', 'Uydu, bu basitlestirilmis model icin secilen Roche sinirinin disindadir.'],
|
|
144
|
+
['1.00x ila 1.12x', 'Gelgit temasi', 'Cisim, deformasyon, catlama veya yuzey dokulmesinin onemli olabilecegi kadar yakindir.'],
|
|
145
|
+
['0.78x ila 1.00x', 'Parcalaniyor', 'Secilen modelde kendi kutle cekimi yeterli degildir; enkaz akislari olasi hale gelir.'],
|
|
146
|
+
['0.78x alti', 'Halka sistemi', 'Orijinal cisim, komsu yorungeleri izleyen dagilmis malzeme olarak temsil edilir.'],
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'paragraph',
|
|
151
|
+
html: 'Yorunge periyodu gostergesi dahil edilmistir, cunku yakin gecisler sadece mesafeyle ilgili degildir. Parcalanma bolgesinin icindeki malzeme, hizli ve birbirinden hafifce farkli yorungeleri izler. Parcalar ayrildiktan sonra, yorunge kaymasi onlari gezegenin etrafina yayarken, carpismalar enkazi duzlestirir ve bir disk benzeri halka halinde siralar.',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
type: 'title',
|
|
155
|
+
text: 'Roche Siniri Neden Halka Olusturabilir',
|
|
156
|
+
level: 3,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
type: 'paragraph',
|
|
160
|
+
html: 'Bir uydu Roche sinirinin disinda parcalandiginda, parcalar zamanla carpisip daha kucuk bir ay halinde yeniden birlesebilir. Roche sinirinin icinde, yakin parcalar kolayca tek bir kararli kutle cekim cismi halinde birlesemez, cunku gelgit kuvvetleri malzemeyi ayirmaya devam eder. Sonuc, ozellikle enkaz buzlu, carpismali ve kucuk aylar veya rezonanslar tarafindan surekli karistirildiginda, uzun omurlu bir halka olabilir.',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'paragraph',
|
|
164
|
+
html: 'Halka olusumu kademelidir. Parcalanan bir ay once uzar, sonra parcaciklar ve daha buyuk parcalar dokulur. Bu parcalar hafifce farkli yorunge yaricapLarinda bulunur, bu nedenle birbirlerinin onune veya arkasina gecerler. Zamanla, carpismalar dikey hareketi sondurur ve malzeme ince bir disk halinde yerlesir. Bu nedenle simulator, parcalanmayi anlik bir patlama olarak ele almak yerine, tek bir aydan yaylara ve daha sonra daha genis bir halkaya gecisi gosterir.',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'title',
|
|
168
|
+
text: 'Bu Roche Siniri Hesaplayicisinin Onemli Sinirlamalari',
|
|
169
|
+
level: 3,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: 'paragraph',
|
|
173
|
+
html: 'Bu hesaplayici, hizli bilimsel sezgi icin tasarlanmistir, yuksek dogruluklu gorev tasarimi icin degildir. Gercek uydular; donus, yorunge dis merkezligi, ic katmanlasma, cekme dayanimi, gozeneklilik, sicaklik, gelgit isinmasi, onceden olusan catlaklar, carpmalar ve diger aylarla rezonanslardan etkilenir. Dis merkezli bir yorungede donen bir moloz yigini, ortalama yogunluklari benzer gorunse bile, dairesel bir yorungedeki soguk monolitik bir kayadan farkli sekilde parcalanabilir.',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'list',
|
|
177
|
+
items: [
|
|
178
|
+
'<strong>Akiskan limitini kullanin</strong> cisim zayif, buzlu, erimis, ileri derecede catlakli veya gevsek yigindan olusuyorsa.',
|
|
179
|
+
'<strong>Kati limitini kullanin</strong> anlamli ic dayanima sahip kompakt cisimler icin bir alt sinir tahmini olarak.',
|
|
180
|
+
'<strong>Aktif limiti okuyun</strong> simulatorun secilen uydu turu icin sectigi calisma siniri olarak.',
|
|
181
|
+
'<strong>Sonucu, adi gecen gercek bir ay icin</strong> detayli bir jeofizik model olmadan kesin bir tahmin olarak okumayin.',
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'title',
|
|
186
|
+
text: 'Bu Aracin Yanitlamaya Yardimci Oldugu Yaygin Sorular',
|
|
187
|
+
level: 3,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'paragraph',
|
|
191
|
+
html: 'Su tur sorulari tahmin etmek istediginizde bu araci kullanin: Bir ay, parcalanmadan Dunya\'ya ne kadar yaklasabilir? Saturn\'un halkalari neden bir Roche siniri bolgesinin icindedir? Kayali bir ay, buzlu bir aydan daha yakin hayatta kalabilir mi? Yogunluk Roche sinirini nasil degistirir? Akiskan ve kati Roche siniri arasindaki fark nedir? Kontroller bu karsilastirmalar etrafinda yapilandirilmistir, bu nedenle bir degiskeni degistirmek, kirilma mesafesi, guvenlik orani ve halka olusumu gorsellestirmesinin nasil tepki verdigini aninda gosterir.',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
faq,
|
|
195
|
+
bibliography,
|
|
196
|
+
howTo,
|
|
197
|
+
schemas: [
|
|
198
|
+
{
|
|
199
|
+
'@context': 'https://schema.org',
|
|
200
|
+
'@type': 'SoftwareApplication',
|
|
201
|
+
name: title,
|
|
202
|
+
description,
|
|
203
|
+
applicationCategory: 'ScientificApplication',
|
|
204
|
+
operatingSystem: 'Any',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
'@context': 'https://schema.org',
|
|
208
|
+
'@type': 'FAQPage',
|
|
209
|
+
mainEntity: faq.map((item) => ({
|
|
210
|
+
'@type': 'Question',
|
|
211
|
+
name: item.question,
|
|
212
|
+
acceptedAnswer: {
|
|
213
|
+
'@type': 'Answer',
|
|
214
|
+
text: item.answer,
|
|
215
|
+
},
|
|
216
|
+
})),
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
'@context': 'https://schema.org',
|
|
220
|
+
'@type': 'HowTo',
|
|
221
|
+
name: title,
|
|
222
|
+
step: howTo.map((step) => ({
|
|
223
|
+
'@type': 'HowToStep',
|
|
224
|
+
name: step.name,
|
|
225
|
+
text: step.text,
|
|
226
|
+
})),
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
|
|
4
|
+
const slug = 'roche-limit-satellite-disruption';
|
|
5
|
+
const title = '洛希极限计算器与卫星解体模拟器';
|
|
6
|
+
const description = '计算行星与卫星的洛希极限,比较流体与刚性解体距离,可视化潮汐力如何将卫星转变为环系统。';
|
|
7
|
+
|
|
8
|
+
const howTo = [
|
|
9
|
+
{
|
|
10
|
+
name: '选择主天体',
|
|
11
|
+
text: '选择拉伸卫星的行星。计算器将加载其半径、密度和质量,用于洛希极限和轨道周期估算。',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: '选择卫星类型',
|
|
15
|
+
text: '选择冰卫星、岩石卫星、碎石堆或富铁天体。密度和内聚力的不同会改变解体边界。',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: '移动轨道滑块',
|
|
19
|
+
text: '向内或向外拖动轨道距离。视觉圆盘会显示卫星处于洛希极限之外、擦碰极限、正在碎裂还是已变为环。',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: '比较极限值',
|
|
23
|
+
text: '使用读数比较经典流体洛希极限与较低的刚性体估算值以及经内聚力调整的有效极限。',
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const faq = [
|
|
28
|
+
{
|
|
29
|
+
question: '什么是洛希极限?',
|
|
30
|
+
answer: '洛希极限是距离大质量主天体的一段距离,在此距离处,跨越较小轨道天体的潮汐力变得足够强,足以克服该小天体的自引力。在该边界以内,脆弱的或类流体的卫星可能被撕裂。',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
question: '为什么有流体洛希极限和刚性洛希极限之分?',
|
|
34
|
+
answer: '流体卫星容易变形,潮汐力可以加剧其拉长,使其在更远的距离外被瓦解。刚性卫星凭借材料强度抵抗变形,因此简单的刚性估算将解体位置估算得更靠近主天体。',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: '洛希极限内的每个卫星都会立即变成环吗?',
|
|
38
|
+
answer: '不会。真实的解体取决于自转、成分、裂缝、孔隙率、加热、撞击和材料强度。本工具展示的是经典引力边界,并采用过渡带来传达风险,而不是一个瞬间切换的开关。',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
question: '为什么土星环位于洛希极限附近?',
|
|
42
|
+
answer: '土星环占据了一个区域,在此区域中冰物质可以以颗粒形式存在,而不是聚集成一颗大卫星。洛希极限有助于解释为什么环颗粒能够在靠近行星的地方保持分散。',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const content: ToolLocaleContent = {
|
|
47
|
+
slug,
|
|
48
|
+
title,
|
|
49
|
+
description,
|
|
50
|
+
ui: {
|
|
51
|
+
primaryBody: '主天体',
|
|
52
|
+
satelliteType: '卫星类型',
|
|
53
|
+
orbitDistance: '轨道距离',
|
|
54
|
+
rocheBoundary: '洛希边界',
|
|
55
|
+
fluidLimit: '流体极限',
|
|
56
|
+
rigidLimit: '刚性极限',
|
|
57
|
+
activeLimit: '有效极限',
|
|
58
|
+
safetyRatio: '安全比率',
|
|
59
|
+
orbitalPeriod: '轨道周期',
|
|
60
|
+
tidalStress: '潮汐应力',
|
|
61
|
+
ringFormation: '环形成',
|
|
62
|
+
stable: '稳定轨道',
|
|
63
|
+
grazing: '潮汐擦碰',
|
|
64
|
+
fragmenting: '碎裂中',
|
|
65
|
+
ring: '环系统',
|
|
66
|
+
km: 'km',
|
|
67
|
+
hours: '小时',
|
|
68
|
+
density: '密度',
|
|
69
|
+
cohesion: '内聚力',
|
|
70
|
+
planetRadius: '行星半径',
|
|
71
|
+
reset: '重置',
|
|
72
|
+
closePass: '近距离飞越',
|
|
73
|
+
moonTrack: '卫星轨迹',
|
|
74
|
+
debrisTrack: '碎片轨迹',
|
|
75
|
+
},
|
|
76
|
+
seo: [
|
|
77
|
+
{
|
|
78
|
+
type: 'title',
|
|
79
|
+
text: '洛希极限公式、含义及如何使用本计算器',
|
|
80
|
+
level: 2,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: 'paragraph',
|
|
84
|
+
html: '<strong>洛希极限</strong>是指一颗主要靠自身引力维持的卫星在绕大天体运行时,不会被潮汐力撕裂的最小轨道距离。人们通常搜索它,是为了想知道某颗卫星、彗星、小行星或人造场景能否在近距离飞越行星时幸存,或者物质是否会扩散成环。本计算器通过结合行星半径、行星密度、卫星密度以及卫星的近似内部强度来回答这个问题。',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: 'paragraph',
|
|
88
|
+
html: '关键思想很简单:引力在卫星上并非均匀分布。近端受到的拉力大于远端,从而产生拉伸力。如果这种潮汐拉伸力强于卫星的自引力和物质内聚力,天体就会破裂、脱落质量并最终碎裂。因此,洛希极限不仅仅是一个距离;它是外部潮汐应力与内部结合力之间的比较。',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
type: 'title',
|
|
92
|
+
text: '计算器使用的洛希极限公式',
|
|
93
|
+
level: 3,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'paragraph',
|
|
97
|
+
html: '对于流体或非常弱的卫星,经典近似公式为 <strong>d = 2.44 R (rho_M / rho_m)^(1/3)</strong>。对于刚性卫星,常用近似公式为 <strong>d = 1.26 R (rho_M / rho_m)^(1/3)</strong>。在这些公式中,<strong>d</strong> 是从行星中心测量的洛希极限,<strong>R</strong> 是主天体的半径,<strong>rho_M</strong> 是主天体的密度,<strong>rho_m</strong> 是卫星的密度。',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'list',
|
|
101
|
+
items: [
|
|
102
|
+
'<strong>主天体半径:</strong>即使密度相似,较大的行星也会产生更大的洛希极限距离。',
|
|
103
|
+
'<strong>主天体密度:</strong>密度较大的主天体在给定半径倍数处会增强潮汐强度。',
|
|
104
|
+
'<strong>卫星密度:</strong>密度较大的卫星具有更强的自引力,因此可以在更靠近行星的位置幸存。',
|
|
105
|
+
'<strong>卫星强度:</strong>流体状、冰质、破裂或碎石堆天体比致密的刚性天体在更远处解体。',
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'table',
|
|
110
|
+
headers: ['模型', '公式形式', '适用场景', '结果含义'],
|
|
111
|
+
rows: [
|
|
112
|
+
['流体洛希极限', '2.44 R (rho_M / rho_m)^(1/3)', '冰卫星、熔融天体、碎石堆、弱彗星', '易于变形的天体的保守解体距离。'],
|
|
113
|
+
['刚性洛希极限', '1.26 R (rho_M / rho_m)^(1/3)', '具有材料强度的致密岩石或金属天体', '材料强度延缓解体的较近下限估算值。'],
|
|
114
|
+
['内聚力调整显示', '介于流体和刚性之间', '本模拟器中的快速场景比较', '针对所选卫星类型的实用风险线,并非普遍的自然法则开关。'],
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'title',
|
|
119
|
+
text: '示例:为什么土星附近的冰卫星容易解体',
|
|
120
|
+
level: 3,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'paragraph',
|
|
124
|
+
html: '土星的密度远小于地球,但它体积巨大。低密度的冰卫星自引力较弱,无法与致密的岩石卫星相比,因此密度比仍然使流体洛希极限远离土星的云顶。这就是为什么洛希极限物理学对于理解土星为何能维持一个宽广明亮的、主要由冰颗粒组成而非一颗重新聚集的大卫星的环系统至关重要。',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: 'paragraph',
|
|
128
|
+
html: '如果在计算器中选择土星和一颗冰卫星,然后向内拖动轨道,观察安全比率。当比率高于 <strong>1.00x</strong> 时,所选轨道位于有效洛希边界之外。接近 <strong>1.00x</strong> 时,卫星处于潮汐擦碰区域,质量脱落或破裂成为可能。低于 <strong>1.00x</strong> 时,可视化向碎片弧和环形成转变,因为所选模型预测会发生解体。',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: 'title',
|
|
132
|
+
text: '如何解读安全比率',
|
|
133
|
+
level: 3,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
type: 'paragraph',
|
|
137
|
+
html: '<strong>安全比率</strong>是当前轨道距离除以所选洛希边界。比率为 <strong>1.25x</strong> 意味着轨道比有效解体估算值远 25%。比率为 <strong>1.00x</strong> 意味着轨道恰好位于所选洛希边界上。比率为 <strong>0.80x</strong> 意味着卫星已深入所选解体区域内部。',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: 'table',
|
|
141
|
+
headers: ['安全比率', '显示状态', '实际含义'],
|
|
142
|
+
rows: [
|
|
143
|
+
['高于 1.12x', '稳定轨道', '卫星在此简化模型中位于所选洛希边界之外。'],
|
|
144
|
+
['1.00x 至 1.12x', '潮汐擦碰', '天体足够近,变形、破裂或表面脱落可能产生影响。'],
|
|
145
|
+
['0.78x 至 1.00x', '碎裂中', '在所选模型中,自引力已不足以维持;碎片流是可能的。'],
|
|
146
|
+
['低于 0.78x', '环系统', '原始天体被表示为沿相邻轨道散布的物质。'],
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'paragraph',
|
|
151
|
+
html: '显示轨道周期的原因在于,近距离飞越不仅关乎距离。解体区域内的物质沿快速、略有差异的轨道运动。一旦碎片分离,轨道剪切力将它们散布在行星周围,而碰撞则使碎片扁平化并按大小分选,形成盘状环。',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
type: 'title',
|
|
155
|
+
text: '为什么洛希极限能产生环',
|
|
156
|
+
level: 3,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
type: 'paragraph',
|
|
160
|
+
html: '当卫星在洛希极限外碎裂时,碎片最终可能碰撞并重新聚集成一颗较小的卫星。在洛希极限内,附近的碎片难以合并成一个稳定的自引力天体,因为潮汐力不断将物质拉开。其结果可能是一个长寿命的环,尤其是当碎片是冰质的、存在碰撞、并受到小卫星或共振持续扰动时。',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'paragraph',
|
|
164
|
+
html: '环的形成是渐进的。一颗被瓦解的卫星首先被拉长,然后脱落颗粒和较大的碎片。这些碎片占据略有不同的轨道半径,因此它们会彼此超前或滞后。随着时间的推移,碰撞抑制了垂直运动,物质沉降成一个薄盘。这就是为什么模拟器展示的是从单颗卫星到碎片弧再到更完整的环的过渡,而不是将解体视为一次瞬间爆炸。',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'title',
|
|
168
|
+
text: '本洛希极限计算器的重要限制',
|
|
169
|
+
level: 3,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: 'paragraph',
|
|
173
|
+
html: '本计算器旨在提供快速的科学直觉,而非高保真的任务设计。真实的卫星受到自转、轨道偏心率、内部分层、抗拉强度、孔隙率、温度、潮汐加热、既有裂缝、撞击以及其他卫星的共振影响。一个在偏心轨道上旋转的碎石堆与一个在圆形轨道上的寒冷整体岩石可能以不同的方式失效,即使它们的平均密度看起来相似。',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'list',
|
|
177
|
+
items: [
|
|
178
|
+
'<strong>使用流体极限</strong>适用于弱的、冰质的、熔融的、高度碎裂的或由松散集合体组成的天体。',
|
|
179
|
+
'<strong>使用刚性极限</strong>作为具有实际内部强度的致密天体的下限估算值。',
|
|
180
|
+
'<strong>读取有效极限</strong>作为模拟器针对所选卫星类型选择的工作边界。',
|
|
181
|
+
'<strong>不要将结果</strong>解读为对某个真实命名卫星的精确预测,这需要详细的地球物理模型。',
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'title',
|
|
186
|
+
text: '本工具帮助解答的常见问题',
|
|
187
|
+
level: 3,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'paragraph',
|
|
191
|
+
html: '使用本工具来估算以下问题:一颗卫星在解体前能距离地球多近?为什么土星环位于洛希极限区域内?岩石卫星是否比冰卫星能在更近的距离幸存?密度如何改变洛希极限?流体洛希极限和刚性洛希极限有什么区别?控制组件正是围绕这些比较而构建,因此改变一个变量即可立即显示解体距离、安全比率和环形成可视化如何响应。',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
faq,
|
|
195
|
+
bibliography,
|
|
196
|
+
howTo,
|
|
197
|
+
schemas: [
|
|
198
|
+
{
|
|
199
|
+
'@context': 'https://schema.org',
|
|
200
|
+
'@type': 'SoftwareApplication',
|
|
201
|
+
name: title,
|
|
202
|
+
description,
|
|
203
|
+
applicationCategory: 'ScientificApplication',
|
|
204
|
+
operatingSystem: 'Any',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
'@context': 'https://schema.org',
|
|
208
|
+
'@type': 'FAQPage',
|
|
209
|
+
mainEntity: faq.map((item) => ({
|
|
210
|
+
'@type': 'Question',
|
|
211
|
+
name: item.question,
|
|
212
|
+
acceptedAnswer: {
|
|
213
|
+
'@type': 'Answer',
|
|
214
|
+
text: item.answer,
|
|
215
|
+
},
|
|
216
|
+
})),
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
'@context': 'https://schema.org',
|
|
220
|
+
'@type': 'HowTo',
|
|
221
|
+
name: title,
|
|
222
|
+
step: howTo.map((step) => ({
|
|
223
|
+
'@type': 'HowToStep',
|
|
224
|
+
name: step.name,
|
|
225
|
+
text: step.text,
|
|
226
|
+
})),
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { rocheLimitSatelliteDisruption } from './entry';
|
|
2
|
+
import type { ToolDefinition } from '../../types';
|
|
3
|
+
|
|
4
|
+
export * from './entry';
|
|
5
|
+
|
|
6
|
+
export const ROCHE_LIMIT_SATELLITE_DISRUPTION_TOOL: ToolDefinition = {
|
|
7
|
+
entry: rocheLimitSatelliteDisruption,
|
|
8
|
+
Component: () => import('./component.astro'),
|
|
9
|
+
SEOComponent: () => import('./seo.astro'),
|
|
10
|
+
BibliographyComponent: () => import('./bibliography.astro'),
|
|
11
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export type PrimaryId = 'earth' | 'mars' | 'jupiter' | 'saturn' | 'neptune';
|
|
2
|
+
export type SatelliteId = 'icy-moon' | 'rocky-moon' | 'rubble-pile' | 'iron-core';
|
|
3
|
+
|
|
4
|
+
export interface PrimaryBody {
|
|
5
|
+
id: PrimaryId;
|
|
6
|
+
name: string;
|
|
7
|
+
radiusKm: number;
|
|
8
|
+
densityGcm3: number;
|
|
9
|
+
massKg: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SatelliteBody {
|
|
13
|
+
id: SatelliteId;
|
|
14
|
+
name: string;
|
|
15
|
+
densityGcm3: number;
|
|
16
|
+
radiusKm: number;
|
|
17
|
+
cohesion: 'fluid' | 'fractured' | 'rigid';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RocheInput {
|
|
21
|
+
primaryId: PrimaryId;
|
|
22
|
+
satelliteId: SatelliteId;
|
|
23
|
+
orbitDistanceKm: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RocheResult {
|
|
27
|
+
primary: PrimaryBody;
|
|
28
|
+
satellite: SatelliteBody;
|
|
29
|
+
fluidLimitKm: number;
|
|
30
|
+
rigidLimitKm: number;
|
|
31
|
+
selectedLimitKm: number;
|
|
32
|
+
safetyRatio: number;
|
|
33
|
+
tidalStressIndex: number;
|
|
34
|
+
ringProgress: number;
|
|
35
|
+
orbitalPeriodHours: number;
|
|
36
|
+
verdict: 'stable' | 'grazing' | 'fragmenting' | 'ring';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const GRAVITATIONAL_CONSTANT = 6.6743e-11;
|
|
40
|
+
|
|
41
|
+
export const PRIMARY_BODIES: PrimaryBody[] = [
|
|
42
|
+
{ id: 'earth', name: 'Earth', radiusKm: 6371, densityGcm3: 5.51, massKg: 5.972e24 },
|
|
43
|
+
{ id: 'mars', name: 'Mars', radiusKm: 3390, densityGcm3: 3.93, massKg: 6.417e23 },
|
|
44
|
+
{ id: 'jupiter', name: 'Jupiter', radiusKm: 69911, densityGcm3: 1.33, massKg: 1.898e27 },
|
|
45
|
+
{ id: 'saturn', name: 'Saturn', radiusKm: 58232, densityGcm3: 0.69, massKg: 5.683e26 },
|
|
46
|
+
{ id: 'neptune', name: 'Neptune', radiusKm: 24622, densityGcm3: 1.64, massKg: 1.024e26 },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export const SATELLITE_BODIES: SatelliteBody[] = [
|
|
50
|
+
{ id: 'icy-moon', name: 'Icy moon', densityGcm3: 0.93, radiusKm: 760, cohesion: 'fluid' },
|
|
51
|
+
{ id: 'rocky-moon', name: 'Rocky moon', densityGcm3: 3.34, radiusKm: 1737, cohesion: 'fractured' },
|
|
52
|
+
{ id: 'rubble-pile', name: 'Rubble pile', densityGcm3: 1.75, radiusKm: 45, cohesion: 'fluid' },
|
|
53
|
+
{ id: 'iron-core', name: 'Iron-rich moon', densityGcm3: 5.3, radiusKm: 980, cohesion: 'rigid' },
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
function findPrimary(id: PrimaryId): PrimaryBody {
|
|
57
|
+
return PRIMARY_BODIES.find((body) => body.id === id) ?? PRIMARY_BODIES[0];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function findSatellite(id: SatelliteId): SatelliteBody {
|
|
61
|
+
return SATELLITE_BODIES.find((body) => body.id === id) ?? SATELLITE_BODIES[0];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function selectedLimitFor(satellite: SatelliteBody, fluidLimitKm: number, rigidLimitKm: number): number {
|
|
65
|
+
if (satellite.cohesion === 'rigid') return rigidLimitKm;
|
|
66
|
+
if (satellite.cohesion === 'fractured') return (fluidLimitKm + rigidLimitKm) / 2;
|
|
67
|
+
return fluidLimitKm;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function verdictFor(safetyRatio: number): RocheResult['verdict'] {
|
|
71
|
+
if (safetyRatio < 0.78) return 'ring';
|
|
72
|
+
if (safetyRatio < 1) return 'fragmenting';
|
|
73
|
+
if (safetyRatio < 1.12) return 'grazing';
|
|
74
|
+
return 'stable';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function calculateRocheLimit(input: RocheInput): RocheResult {
|
|
78
|
+
const primary = findPrimary(input.primaryId);
|
|
79
|
+
const satellite = findSatellite(input.satelliteId);
|
|
80
|
+
const densityRatio = primary.densityGcm3 / satellite.densityGcm3;
|
|
81
|
+
const fluidLimitKm = 2.44 * primary.radiusKm * Math.cbrt(densityRatio);
|
|
82
|
+
const rigidLimitKm = 1.26 * primary.radiusKm * Math.cbrt(densityRatio);
|
|
83
|
+
const selectedLimitKm = selectedLimitFor(satellite, fluidLimitKm, rigidLimitKm);
|
|
84
|
+
const orbitDistanceKm = Math.max(primary.radiusKm * 1.02, input.orbitDistanceKm);
|
|
85
|
+
const safetyRatio = orbitDistanceKm / selectedLimitKm;
|
|
86
|
+
const tidalStressIndex = Math.min(2.2, Math.pow(selectedLimitKm / orbitDistanceKm, 3));
|
|
87
|
+
const ringProgress = Math.max(0, Math.min(1, (1.08 - safetyRatio) / 0.38));
|
|
88
|
+
const orbitalPeriodHours = 2 * Math.PI * Math.sqrt(Math.pow(orbitDistanceKm * 1000, 3) / (GRAVITATIONAL_CONSTANT * primary.massKg)) / 3600;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
primary,
|
|
92
|
+
satellite,
|
|
93
|
+
fluidLimitKm,
|
|
94
|
+
rigidLimitKm,
|
|
95
|
+
selectedLimitKm,
|
|
96
|
+
safetyRatio,
|
|
97
|
+
tidalStressIndex,
|
|
98
|
+
ringProgress,
|
|
99
|
+
orbitalPeriodHours,
|
|
100
|
+
verdict: verdictFor(safetyRatio),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export type VisualState = 'orbiting' | 'deforming' | 'disrupting' | 'ringFormed';
|
|
2
|
+
|
|
3
|
+
export interface ParticleState {
|
|
4
|
+
moon: { x: number; y: number; orbitRadius: number; progress: number };
|
|
5
|
+
visualState: VisualState;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const particles = Array.from({ length: 90 }, (_, index) => ({
|
|
9
|
+
angle: index * 0.42,
|
|
10
|
+
radiusOffset: (index % 9) - 4,
|
|
11
|
+
speed: 0.006 + (index % 7) * 0.0012,
|
|
12
|
+
life: 0,
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
export function resizeParticleCanvas(canvas: HTMLCanvasElement): void {
|
|
16
|
+
const rect = canvas.getBoundingClientRect();
|
|
17
|
+
const scale = window.devicePixelRatio || 1;
|
|
18
|
+
canvas.width = Math.max(1, Math.floor(rect.width * scale));
|
|
19
|
+
canvas.height = Math.max(1, Math.floor(rect.height * scale));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function animateParticles(canvas: HTMLCanvasElement, getState: () => ParticleState): void {
|
|
23
|
+
const context = canvas.getContext('2d');
|
|
24
|
+
if (!context) return;
|
|
25
|
+
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
26
|
+
const state = getState();
|
|
27
|
+
if (state.moon.progress > 0.01) drawParticleFrame(canvas, context, state);
|
|
28
|
+
window.requestAnimationFrame(() => animateParticles(canvas, getState));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function drawParticleFrame(canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, state: ParticleState): void {
|
|
32
|
+
const scaleX = canvas.width / 560;
|
|
33
|
+
const scaleY = canvas.height / 560;
|
|
34
|
+
particles.forEach((particle, index) => {
|
|
35
|
+
const formed = state.visualState === 'ringFormed';
|
|
36
|
+
particle.life = formed ? 1 : (particle.life + state.moon.progress * 0.018 + 0.004) % 1;
|
|
37
|
+
particle.angle += particle.speed * (1 + state.moon.progress * 2.4);
|
|
38
|
+
const release = formed ? 1 : Math.min(1, particle.life * 1.35);
|
|
39
|
+
const angle = particle.angle + index;
|
|
40
|
+
const ringX = 280 + Math.cos(angle) * (state.moon.orbitRadius + particle.radiusOffset * 3.2);
|
|
41
|
+
const ringY = 280 + Math.sin(angle) * (state.moon.orbitRadius * 0.31 + particle.radiusOffset);
|
|
42
|
+
drawParticle(context, {
|
|
43
|
+
x: state.moon.x + (ringX - state.moon.x) * release,
|
|
44
|
+
y: state.moon.y + (ringY - state.moon.y) * release,
|
|
45
|
+
angle,
|
|
46
|
+
frontSide: Math.sin(angle) > 0,
|
|
47
|
+
scaleX,
|
|
48
|
+
scaleY,
|
|
49
|
+
progress: state.moon.progress,
|
|
50
|
+
visualState: state.visualState,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function drawParticle(context: CanvasRenderingContext2D, point: { x: number; y: number; angle: number; frontSide: boolean; scaleX: number; scaleY: number; progress: number; visualState: VisualState }): void {
|
|
56
|
+
const isDarkTheme = document.documentElement.classList.contains('theme-dark');
|
|
57
|
+
let alpha = point.progress * 0.58;
|
|
58
|
+
if (point.visualState === 'ringFormed') alpha = point.frontSide ? 0.72 : 0.26;
|
|
59
|
+
context.strokeStyle = `rgba(${isDarkTheme ? '248, 214, 109' : '93, 70, 30'}, ${0.16 + alpha})`;
|
|
60
|
+
context.lineCap = 'round';
|
|
61
|
+
context.lineWidth = Math.max(1, (point.frontSide ? 1.65 : 0.9) * point.scaleX);
|
|
62
|
+
context.beginPath();
|
|
63
|
+
context.moveTo(point.x * point.scaleX, point.y * point.scaleY);
|
|
64
|
+
context.lineTo((point.x + Math.cos(point.angle) * 6) * point.scaleX, (point.y + Math.sin(point.angle) * 3) * point.scaleY);
|
|
65
|
+
context.stroke();
|
|
66
|
+
}
|