s3m-maplibre 0.2.10 → 0.2.11

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/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  **在 MapLibre GL JS 里原生渲染 SuperMap S3M 三维模型** —— 浏览器直接解析 `.s3mb` 瓦片,不需要预先转成 3D Tiles,也不需要 SuperMap 的 WebGL 客户端。
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/s3m-maplibre?color=blue&label=npm)](https://www.npmjs.com/package/s3m-maplibre)
6
+ [![docs](https://img.shields.io/badge/docs-online-38bdf8)](https://joo1es.github.io/s3m-maplibre/docs/index.html)
6
7
  [![demo](https://img.shields.io/badge/demo-online-2ea44f)](https://joo1es.github.io/s3m-maplibre/demo/index.html)
7
8
  [![license](https://img.shields.io/badge/license-Apache--2.0-green)](./LICENSE)
8
9
  [![types](https://img.shields.io/badge/types-included-blue)](./src/index.ts)
@@ -137,18 +138,18 @@ map.on('click', (e) => {
137
138
  });
138
139
  ```
139
140
 
140
- 完整接口见 **[docs/API.md](./docs/API.md)**。
141
+ 完整接口见 **[开发指南与 API 文档(在线网页)](https://joo1es.github.io/s3m-maplibre/docs/index.html)** 或本地 **[docs/API.md](./docs/API.md)**。
141
142
 
142
143
  ---
143
144
 
144
- ## 演示
145
+ ## 演示与在线文档
145
146
 
146
- 在线跑(GitHub Pages,数据随仓库一起发布):
147
+ 在线体验与文档(GitHub Pages,数据随仓库一起发布):
147
148
 
148
- - **MapLibre 版** — <https://joo1es.github.io/s3m-maplibre/demo/index.html>
149
- - **纯 three.js 版** — <https://joo1es.github.io/s3m-maplibre/demo/three.html>
150
-
151
- (<https://joo1es.github.io/s3m-maplibre/> 是入口页,两个示例都能进)
149
+ - **📚 完整开发指南 & API 文档** — <https://joo1es.github.io/s3m-maplibre/docs/index.html>
150
+ - **🗺️ MapLibre 版演示** — <https://joo1es.github.io/s3m-maplibre/demo/index.html>
151
+ - **🧊 纯 three.js 版演示** — <https://joo1es.github.io/s3m-maplibre/demo/three.html>
152
+ - **🏠 Pages 导航入口** — <https://joo1es.github.io/s3m-maplibre/>
152
153
 
153
154
  本地跑:
154
155
 
package/docs/index.html CHANGED
@@ -146,13 +146,108 @@
146
146
  padding-left: 0.5rem;
147
147
  }
148
148
 
149
- .table-responsive th, .table-responsive td {
150
- padding: 0.75rem 1rem;
151
- vertical-align: top;
149
+ /* 暗黑 / 明亮主题适配 */
150
+ html.dark body {
151
+ background-color: #0b101b;
152
+ color: #cbd5e1;
153
+ }
154
+ html:not(.dark) body {
155
+ background-color: #f8fafc;
156
+ color: #334155;
157
+ }
158
+ html:not(.dark) header {
159
+ background-color: rgba(255, 255, 255, 0.9) !important;
160
+ border-color: rgba(0, 0, 0, 0.08) !important;
161
+ }
162
+ html:not(.dark) header a {
163
+ color: #0f172a !important;
164
+ }
165
+ html:not(.dark) #searchInput {
166
+ background-color: #f1f5f9;
167
+ border-color: #cbd5e1;
168
+ color: #0f172a;
169
+ }
170
+ html:not(.dark) #sidebar {
171
+ border-color: rgba(0, 0, 0, 0.06) !important;
172
+ }
173
+ html:not(.dark) .sidebar-link {
174
+ color: #64748b;
175
+ }
176
+ html:not(.dark) .sidebar-link:hover {
177
+ background: rgba(0, 0, 0, 0.05);
178
+ color: #0f172a;
179
+ }
180
+ html:not(.dark) .sidebar-link.active {
181
+ background: rgba(14, 165, 233, 0.12);
182
+ color: #0284c7;
183
+ }
184
+ html:not(.dark) .doc-content h1 {
185
+ color: #0f172a;
186
+ border-bottom-color: rgba(0, 0, 0, 0.1);
187
+ }
188
+ html:not(.dark) .doc-content h2 {
189
+ color: #1e293b;
190
+ border-bottom-color: rgba(0, 0, 0, 0.08);
191
+ }
192
+ html:not(.dark) .doc-content h3 {
193
+ color: #334155;
194
+ }
195
+ html:not(.dark) .doc-content p,
196
+ html:not(.dark) .doc-content ul,
197
+ html:not(.dark) .doc-content ol {
198
+ color: #475569;
199
+ }
200
+ html:not(.dark) .doc-content strong {
201
+ color: #0f172a;
202
+ }
203
+ html:not(.dark) .doc-content a {
204
+ color: #0284c7;
205
+ }
206
+ html:not(.dark) .doc-content code:not(pre code) {
207
+ background: #e2e8f0;
208
+ color: #0f172a;
209
+ border-color: #cbd5e1;
210
+ }
211
+ html:not(.dark) .callout {
212
+ background: #f0fdf4 !important;
213
+ border-left-color: #10b981 !important;
214
+ color: #166534 !important;
215
+ }
216
+ html:not(.dark) .table-responsive {
217
+ background: #ffffff !important;
218
+ border-color: #e2e8f0 !important;
219
+ box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05);
220
+ }
221
+ html:not(.dark) .table-responsive thead {
222
+ background: #f8fafc !important;
223
+ color: #1e293b !important;
224
+ border-color: #e2e8f0 !important;
225
+ }
226
+ html:not(.dark) .table-responsive table {
227
+ color: #475569 !important;
228
+ }
229
+ html:not(.dark) .table-responsive tbody {
230
+ divide-color: #f1f5f9 !important;
231
+ }
232
+ html:not(.dark) .toc-link {
233
+ color: #64748b;
234
+ }
235
+ html:not(.dark) .toc-link:hover {
236
+ color: #0284c7;
237
+ }
238
+ html:not(.dark) #tocLinks {
239
+ border-left-color: rgba(0,0,0,0.08) !important;
240
+ }
241
+ html:not(.dark) footer {
242
+ border-top-color: rgba(0,0,0,0.08) !important;
243
+ color: #94a3b8;
244
+ }
245
+ html:not(.dark) footer a:hover {
246
+ color: #0f172a;
152
247
  }
153
248
  </style>
154
249
  </head>
155
- <body class="min-h-screen flex flex-col">
250
+ <body class="min-h-screen flex flex-col transition-colors duration-200">
156
251
 
157
252
  <header class="sticky top-0 z-40 w-full border-b border-white/10 bg-[#0b101b]/90 backdrop-blur-md">
158
253
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
@@ -165,11 +260,11 @@
165
260
  <span>s3m-maplibre</span>
166
261
  </a>
167
262
  <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-mono font-medium bg-cyan-500/10 text-cyan-400 border border-cyan-500/20">
168
- v0.2.10
263
+ v0.2.11
169
264
  </span>
170
265
  </div>
171
266
 
172
- <div class="flex items-center gap-4">
267
+ <div class="flex items-center gap-3">
173
268
  <div class="relative hidden sm:block w-64 lg:w-80">
174
269
  <input
175
270
  id="searchInput"
@@ -180,6 +275,12 @@
180
275
  <span class="absolute right-2.5 top-2 text-[10px] font-mono text-slate-500 border border-white/10 rounded px-1">/</span>
181
276
  </div>
182
277
 
278
+ <!-- 明亮 / 暗黑主题切换按钮 -->
279
+ <button id="themeToggleBtn" class="p-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/5 transition" title="切换深色/浅色主题">
280
+ <svg id="themeMoonIcon" class="w-4 h-4 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path></svg>
281
+ <svg id="themeSunIcon" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 9H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
282
+ </button>
283
+
183
284
  <a href="../demo/index.html" target="_blank" class="hidden md:inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium bg-cyan-500 text-slate-950 font-semibold hover:bg-cyan-400 transition shadow-md shadow-cyan-500/10">
184
285
  <span>在线三维 Demo</span>
185
286
  <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path></svg>
@@ -1461,6 +1562,35 @@ layer.flushOverrides();</code></pre>
1461
1562
  }
1462
1563
  });
1463
1564
  }
1565
+
1566
+ // 主题切换逻辑
1567
+ const themeToggleBtn = document.getElementById('themeToggleBtn');
1568
+ const themeSunIcon = document.getElementById('themeSunIcon');
1569
+ const themeMoonIcon = document.getElementById('themeMoonIcon');
1570
+
1571
+ function updateThemeIcons(isDark) {
1572
+ if (themeSunIcon && themeMoonIcon) {
1573
+ themeSunIcon.classList.toggle('hidden', !isDark);
1574
+ themeMoonIcon.classList.toggle('hidden', isDark);
1575
+ }
1576
+ }
1577
+
1578
+ const savedTheme = localStorage.getItem('s3m_doc_theme');
1579
+ if (savedTheme === 'light') {
1580
+ document.documentElement.classList.remove('dark');
1581
+ updateThemeIcons(false);
1582
+ } else {
1583
+ document.documentElement.classList.add('dark');
1584
+ updateThemeIcons(true);
1585
+ }
1586
+
1587
+ if (themeToggleBtn) {
1588
+ themeToggleBtn.addEventListener('click', () => {
1589
+ const isDark = document.documentElement.classList.toggle('dark');
1590
+ localStorage.setItem('s3m_doc_theme', isDark ? 'dark' : 'light');
1591
+ updateThemeIcons(isDark);
1592
+ });
1593
+ }
1464
1594
  </script>
1465
1595
  </body>
1466
1596
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s3m-maplibre",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "SuperMap S3M 三维模型格式的 MapLibre / Mapbox 原生渲染图层:浏览器内直接解析 .s3mb 瓦片,无需转 3D Tiles,支持多数据集叠加、白膜/按高度/按单体/动态扫描着色、单体级 GPU 拾取与属性查询。",
5
5
  "type": "module",
6
6
  "repository": {
@@ -10,9 +10,9 @@ const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
  const rootDir = path.resolve(__dirname, '..');
12
12
 
13
- // 读取 package.json 获取版本号
13
+ // 读取 package.json 获取唯一真实版本号
14
14
  const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf8'));
15
- const version = pkg.version || '0.2.9';
15
+ const version = pkg.version;
16
16
 
17
17
  // 读取 docs/API.md
18
18
  const apiMdPath = path.join(rootDir, 'docs', 'API.md');
@@ -395,13 +395,108 @@ const htmlTemplate = `<!doctype html>
395
395
  padding-left: 0.5rem;
396
396
  }
397
397
 
398
- .table-responsive th, .table-responsive td {
399
- padding: 0.75rem 1rem;
400
- vertical-align: top;
398
+ /* 暗黑 / 明亮主题适配 */
399
+ html.dark body {
400
+ background-color: #0b101b;
401
+ color: #cbd5e1;
402
+ }
403
+ html:not(.dark) body {
404
+ background-color: #f8fafc;
405
+ color: #334155;
406
+ }
407
+ html:not(.dark) header {
408
+ background-color: rgba(255, 255, 255, 0.9) !important;
409
+ border-color: rgba(0, 0, 0, 0.08) !important;
410
+ }
411
+ html:not(.dark) header a {
412
+ color: #0f172a !important;
413
+ }
414
+ html:not(.dark) #searchInput {
415
+ background-color: #f1f5f9;
416
+ border-color: #cbd5e1;
417
+ color: #0f172a;
418
+ }
419
+ html:not(.dark) #sidebar {
420
+ border-color: rgba(0, 0, 0, 0.06) !important;
421
+ }
422
+ html:not(.dark) .sidebar-link {
423
+ color: #64748b;
424
+ }
425
+ html:not(.dark) .sidebar-link:hover {
426
+ background: rgba(0, 0, 0, 0.05);
427
+ color: #0f172a;
428
+ }
429
+ html:not(.dark) .sidebar-link.active {
430
+ background: rgba(14, 165, 233, 0.12);
431
+ color: #0284c7;
432
+ }
433
+ html:not(.dark) .doc-content h1 {
434
+ color: #0f172a;
435
+ border-bottom-color: rgba(0, 0, 0, 0.1);
436
+ }
437
+ html:not(.dark) .doc-content h2 {
438
+ color: #1e293b;
439
+ border-bottom-color: rgba(0, 0, 0, 0.08);
440
+ }
441
+ html:not(.dark) .doc-content h3 {
442
+ color: #334155;
443
+ }
444
+ html:not(.dark) .doc-content p,
445
+ html:not(.dark) .doc-content ul,
446
+ html:not(.dark) .doc-content ol {
447
+ color: #475569;
448
+ }
449
+ html:not(.dark) .doc-content strong {
450
+ color: #0f172a;
451
+ }
452
+ html:not(.dark) .doc-content a {
453
+ color: #0284c7;
454
+ }
455
+ html:not(.dark) .doc-content code:not(pre code) {
456
+ background: #e2e8f0;
457
+ color: #0f172a;
458
+ border-color: #cbd5e1;
459
+ }
460
+ html:not(.dark) .callout {
461
+ background: #f0fdf4 !important;
462
+ border-left-color: #10b981 !important;
463
+ color: #166534 !important;
464
+ }
465
+ html:not(.dark) .table-responsive {
466
+ background: #ffffff !important;
467
+ border-color: #e2e8f0 !important;
468
+ box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05);
469
+ }
470
+ html:not(.dark) .table-responsive thead {
471
+ background: #f8fafc !important;
472
+ color: #1e293b !important;
473
+ border-color: #e2e8f0 !important;
474
+ }
475
+ html:not(.dark) .table-responsive table {
476
+ color: #475569 !important;
477
+ }
478
+ html:not(.dark) .table-responsive tbody {
479
+ divide-color: #f1f5f9 !important;
480
+ }
481
+ html:not(.dark) .toc-link {
482
+ color: #64748b;
483
+ }
484
+ html:not(.dark) .toc-link:hover {
485
+ color: #0284c7;
486
+ }
487
+ html:not(.dark) #tocLinks {
488
+ border-left-color: rgba(0,0,0,0.08) !important;
489
+ }
490
+ html:not(.dark) footer {
491
+ border-top-color: rgba(0,0,0,0.08) !important;
492
+ color: #94a3b8;
493
+ }
494
+ html:not(.dark) footer a:hover {
495
+ color: #0f172a;
401
496
  }
402
497
  </style>
403
498
  </head>
404
- <body class="min-h-screen flex flex-col">
499
+ <body class="min-h-screen flex flex-col transition-colors duration-200">
405
500
 
406
501
  <header class="sticky top-0 z-40 w-full border-b border-white/10 bg-[#0b101b]/90 backdrop-blur-md">
407
502
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
@@ -418,7 +513,7 @@ const htmlTemplate = `<!doctype html>
418
513
  </span>
419
514
  </div>
420
515
 
421
- <div class="flex items-center gap-4">
516
+ <div class="flex items-center gap-3">
422
517
  <div class="relative hidden sm:block w-64 lg:w-80">
423
518
  <input
424
519
  id="searchInput"
@@ -429,6 +524,12 @@ const htmlTemplate = `<!doctype html>
429
524
  <span class="absolute right-2.5 top-2 text-[10px] font-mono text-slate-500 border border-white/10 rounded px-1">/</span>
430
525
  </div>
431
526
 
527
+ <!-- 明亮 / 暗黑主题切换按钮 -->
528
+ <button id="themeToggleBtn" class="p-2 rounded-lg text-slate-400 hover:text-white hover:bg-white/5 transition" title="切换深色/浅色主题">
529
+ <svg id="themeMoonIcon" class="w-4 h-4 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path></svg>
530
+ <svg id="themeSunIcon" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 9H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
531
+ </button>
532
+
432
533
  <a href="../demo/index.html" target="_blank" class="hidden md:inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium bg-cyan-500 text-slate-950 font-semibold hover:bg-cyan-400 transition shadow-md shadow-cyan-500/10">
433
534
  <span>在线三维 Demo</span>
434
535
  <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path></svg>
@@ -538,6 +639,35 @@ const htmlTemplate = `<!doctype html>
538
639
  }
539
640
  });
540
641
  }
642
+
643
+ // 主题切换逻辑
644
+ const themeToggleBtn = document.getElementById('themeToggleBtn');
645
+ const themeSunIcon = document.getElementById('themeSunIcon');
646
+ const themeMoonIcon = document.getElementById('themeMoonIcon');
647
+
648
+ function updateThemeIcons(isDark) {
649
+ if (themeSunIcon && themeMoonIcon) {
650
+ themeSunIcon.classList.toggle('hidden', !isDark);
651
+ themeMoonIcon.classList.toggle('hidden', isDark);
652
+ }
653
+ }
654
+
655
+ const savedTheme = localStorage.getItem('s3m_doc_theme');
656
+ if (savedTheme === 'light') {
657
+ document.documentElement.classList.remove('dark');
658
+ updateThemeIcons(false);
659
+ } else {
660
+ document.documentElement.classList.add('dark');
661
+ updateThemeIcons(true);
662
+ }
663
+
664
+ if (themeToggleBtn) {
665
+ themeToggleBtn.addEventListener('click', () => {
666
+ const isDark = document.documentElement.classList.toggle('dark');
667
+ localStorage.setItem('s3m_doc_theme', isDark ? 'dark' : 'light');
668
+ updateThemeIcons(isDark);
669
+ });
670
+ }
541
671
  </script>
542
672
  </body>
543
673
  </html>