@trapar-waves/react-three-maplibre 1.1.22 → 1.2.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/README.md +22 -10
- package/environments/.env +2 -1
- package/eslint.config.js +6 -0
- package/package.json +32 -27
- package/pnpm-workspace.yaml +4 -0
- package/readme/README-CN.md +6 -10
- package/readme/README-JP.md +6 -10
- package/readme/README-RU.md +6 -10
- package/rsbuild.config.ts +48 -1
- package/src/App.tsx +124 -6
- package/tsconfig.json +1 -1
package/README.md
CHANGED
|
@@ -25,6 +25,22 @@
|
|
|
25
25
|
- **Map Interactivity:** Implements `react-map-gl` for interactive map controls and client-side navigation in geospatial contexts.
|
|
26
26
|
- **AntV Enhancements:** Incorporates `@antv/l7-maps` for additional map layering capabilities and visualization tools.
|
|
27
27
|
|
|
28
|
+
## GitHub Pages
|
|
29
|
+
|
|
30
|
+
Pushing a version tag matching `v*` runs [`.github/workflows/pages.yml`](./.github/workflows/pages.yml), which builds with `BASE_PATH=/<repository-name>/`, copies `dist/index.html` to `dist/404.html` for SPA routing, and deploys to GitHub Pages. In the repository **Settings → Pages**, set **Source** to **GitHub Actions** once.
|
|
31
|
+
|
|
32
|
+
The demo map uses [Carto Basemaps](https://carto.com/basemaps/) public MapLibre GL styles (**no API key** required for local builds or GitHub Pages).
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
BASE_PATH=/react-three-maplibre/ pnpm run build && pnpm preview
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
PowerShell:
|
|
39
|
+
|
|
40
|
+
```powershell
|
|
41
|
+
$env:BASE_PATH="/react-three-maplibre/"; pnpm run build; pnpm preview
|
|
42
|
+
```
|
|
43
|
+
|
|
28
44
|
## 💻 Tech Stack
|
|
29
45
|
|
|
30
46
|
- **Framework/Library:** React
|
|
@@ -142,7 +158,8 @@ const latLon = {
|
|
|
142
158
|
latitude: 31.215175,
|
|
143
159
|
longitude: 121.417463,
|
|
144
160
|
};
|
|
145
|
-
const
|
|
161
|
+
const MAP_STYLE_URL
|
|
162
|
+
= "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
146
163
|
|
|
147
164
|
function App() {
|
|
148
165
|
const ref = useRef<HTMLDivElement>(null!);
|
|
@@ -187,7 +204,7 @@ function App() {
|
|
|
187
204
|
zoom: 11,
|
|
188
205
|
pitch: 64.88,
|
|
189
206
|
}}
|
|
190
|
-
mapStyle={
|
|
207
|
+
mapStyle={MAP_STYLE_URL}
|
|
191
208
|
onLoad={initL7}
|
|
192
209
|
>
|
|
193
210
|
<Stats className="stats" parent={ref} />
|
|
@@ -211,20 +228,15 @@ export default App;
|
|
|
211
228
|
```
|
|
212
229
|
|
|
213
230
|
This example demonstrates:
|
|
231
|
+
|
|
214
232
|
- Creating a MapLibre GL map with `react-map-gl`
|
|
215
233
|
- Integrating AntV L7 for geospatial data visualization
|
|
216
234
|
- Using React Three Fiber and Drei for 3D rendering
|
|
217
235
|
- Positioning 3D objects relative to the map using `react-three-map`
|
|
218
236
|
|
|
219
|
-
###
|
|
220
|
-
|
|
221
|
-
To use map services like MapTiler, you'll need to set up environment variables. Create a `.env` file in your project root:
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
PUBLIC_MAPTILER_KEY=your_maptiler_api_key_here
|
|
225
|
-
```
|
|
237
|
+
### Map basemap
|
|
226
238
|
|
|
227
|
-
|
|
239
|
+
The template ships with a key-free Carto GL style (`MAP_STYLE_URL` in `src/App.tsx`). To switch providers (e.g. MapTiler), point `mapStyle` at your style JSON and manage API keys via `.env` / CI secrets yourself.
|
|
228
240
|
|
|
229
241
|
## 🤝 Contributing
|
|
230
242
|
|
package/environments/.env
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
# 默认底图为 Carto Basemaps(MapLibre GL),无需在此填写地图 API Key。
|
|
2
|
+
# 若接入 MapTiler 等需鉴权的服务,请自行在代码中配置 mapStyle 并在此添加对应变量。
|
package/eslint.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trapar-waves/react-three-maplibre",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"packageManager": "pnpm@10.
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"packageManager": "pnpm@10.33.2",
|
|
6
6
|
"description": "A React library integrating Three.js and MapLibre for 3D map visualization",
|
|
7
7
|
"author": {
|
|
8
8
|
"email": "admin@rikka.cc",
|
|
@@ -33,42 +33,47 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"dev": "rsbuild dev --open",
|
|
35
35
|
"build": "rsbuild build",
|
|
36
|
+
"build:rsdoctor": "cross-env RSDOCTOR=true rsbuild build",
|
|
36
37
|
"preview": "rsbuild preview",
|
|
37
38
|
"lint": "eslint . --cache --max-warnings=0 --no-warn-ignored",
|
|
38
39
|
"postinstall": "husky"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@antv/l7": "^2.
|
|
42
|
-
"@antv/l7-maps": "^2.
|
|
42
|
+
"@antv/l7": "^2.25.4",
|
|
43
|
+
"@antv/l7-maps": "^2.25.4",
|
|
43
44
|
"@react-three/drei": "^10.7.7",
|
|
44
|
-
"@react-three/fiber": "^9.
|
|
45
|
-
"maplibre-gl": "^5.
|
|
46
|
-
"react": "^19.2.
|
|
47
|
-
"react-dom": "^19.2.
|
|
48
|
-
"react-map-gl": "^8.1.
|
|
45
|
+
"@react-three/fiber": "^9.6.0",
|
|
46
|
+
"maplibre-gl": "^5.24.0",
|
|
47
|
+
"react": "^19.2.5",
|
|
48
|
+
"react-dom": "^19.2.5",
|
|
49
|
+
"react-map-gl": "^8.1.1",
|
|
49
50
|
"react-three-map": "^1.0.0",
|
|
50
|
-
"three": "^0.
|
|
51
|
+
"three": "^0.184.0",
|
|
51
52
|
"three-stdlib": "^2.36.1"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"@antfu/eslint-config": "^
|
|
55
|
-
"@eslint-react/eslint-plugin": "^
|
|
56
|
-
"@iconify/json": "^2.2.
|
|
57
|
-
"@iconify/tailwind4": "^1.2.
|
|
58
|
-
"@rsbuild/core": "^
|
|
59
|
-
"@rsbuild/plugin-
|
|
60
|
-
"@
|
|
61
|
-
"@
|
|
55
|
+
"@antfu/eslint-config": "^8.2.0",
|
|
56
|
+
"@eslint-react/eslint-plugin": "^3.0.0",
|
|
57
|
+
"@iconify/json": "^2.2.467",
|
|
58
|
+
"@iconify/tailwind4": "^1.2.3",
|
|
59
|
+
"@rsbuild/core": "^2.0.1",
|
|
60
|
+
"@rsbuild/plugin-less": "^1.6.2",
|
|
61
|
+
"@rsbuild/plugin-react": "^2.0.0",
|
|
62
|
+
"@rsdoctor/rspack-plugin": "^1.5.9",
|
|
63
|
+
"@tailwindcss/postcss": "^4.2.4",
|
|
64
|
+
"@types/react": "^19.2.14",
|
|
62
65
|
"@types/react-dom": "^19.2.3",
|
|
63
|
-
"@types/three": "^0.
|
|
64
|
-
"
|
|
65
|
-
"eslint
|
|
66
|
-
"eslint-plugin-
|
|
67
|
-
"eslint-plugin-react-
|
|
66
|
+
"@types/three": "^0.184.0",
|
|
67
|
+
"cross-env": "^10.1.0",
|
|
68
|
+
"eslint": "^10.2.1",
|
|
69
|
+
"eslint-plugin-format": "^2.0.1",
|
|
70
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
71
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
68
72
|
"husky": "^9.1.7",
|
|
69
|
-
"lint-staged": "^16.
|
|
70
|
-
"mapbox-gl": "^3.
|
|
71
|
-
"tailwindcss": "^4.
|
|
72
|
-
"typescript": "^
|
|
73
|
+
"lint-staged": "^16.4.0",
|
|
74
|
+
"mapbox-gl": "^3.22.0",
|
|
75
|
+
"tailwindcss": "^4.2.4",
|
|
76
|
+
"typescript": "^6.0.3",
|
|
77
|
+
"unplugin-turbo-console": "^2.3.1"
|
|
73
78
|
}
|
|
74
79
|
}
|
package/pnpm-workspace.yaml
CHANGED
package/readme/README-CN.md
CHANGED
|
@@ -142,7 +142,8 @@ const latLon = {
|
|
|
142
142
|
latitude: 31.215175,
|
|
143
143
|
longitude: 121.417463,
|
|
144
144
|
};
|
|
145
|
-
const
|
|
145
|
+
const MAP_STYLE_URL
|
|
146
|
+
= "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
146
147
|
|
|
147
148
|
function App() {
|
|
148
149
|
const ref = useRef<HTMLDivElement>(null!);
|
|
@@ -187,7 +188,7 @@ function App() {
|
|
|
187
188
|
zoom: 11,
|
|
188
189
|
pitch: 64.88,
|
|
189
190
|
}}
|
|
190
|
-
mapStyle={
|
|
191
|
+
mapStyle={MAP_STYLE_URL}
|
|
191
192
|
onLoad={initL7}
|
|
192
193
|
>
|
|
193
194
|
<Stats className="stats" parent={ref} />
|
|
@@ -211,20 +212,15 @@ export default App;
|
|
|
211
212
|
```
|
|
212
213
|
|
|
213
214
|
这个示例演示了:
|
|
215
|
+
|
|
214
216
|
- 使用 `react-map-gl` 创建 MapLibre GL 地图
|
|
215
217
|
- 集成 AntV L7 进行地理空间数据可视化
|
|
216
218
|
- 使用 React Three Fiber 和 Drei 进行 3D 渲染
|
|
217
219
|
- 使用 `react-three-map` 将 3D 对象相对于地图进行定位
|
|
218
220
|
|
|
219
|
-
###
|
|
220
|
-
|
|
221
|
-
要使用 MapTiler 等地图服务,您需要设置环境变量。在项目根目录创建一个 `.env` 文件:
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
PUBLIC_MAPTILER_KEY=your_maptiler_api_key_here
|
|
225
|
-
```
|
|
221
|
+
### 地图底图
|
|
226
222
|
|
|
227
|
-
|
|
223
|
+
模板默认使用无需 API Key 的 Carto GL 样式(见 `src/App.tsx` 中的 `MAP_STYLE_URL`)。若改用 MapTiler 等需鉴权的服务,请自行设置 `mapStyle` 并通过 `.env` / CI 密钥管理凭据。
|
|
228
224
|
|
|
229
225
|
## 🤝 贡献指南
|
|
230
226
|
|
package/readme/README-JP.md
CHANGED
|
@@ -142,7 +142,8 @@ const latLon = {
|
|
|
142
142
|
latitude: 31.215175,
|
|
143
143
|
longitude: 121.417463,
|
|
144
144
|
};
|
|
145
|
-
const
|
|
145
|
+
const MAP_STYLE_URL
|
|
146
|
+
= "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
146
147
|
|
|
147
148
|
function App() {
|
|
148
149
|
const ref = useRef<HTMLDivElement>(null!);
|
|
@@ -187,7 +188,7 @@ function App() {
|
|
|
187
188
|
zoom: 11,
|
|
188
189
|
pitch: 64.88,
|
|
189
190
|
}}
|
|
190
|
-
mapStyle={
|
|
191
|
+
mapStyle={MAP_STYLE_URL}
|
|
191
192
|
onLoad={initL7}
|
|
192
193
|
>
|
|
193
194
|
<Stats className="stats" parent={ref} />
|
|
@@ -211,20 +212,15 @@ export default App;
|
|
|
211
212
|
```
|
|
212
213
|
|
|
213
214
|
この例では以下を示しています:
|
|
215
|
+
|
|
214
216
|
- `react-map-gl` を使用して MapLibre GL マップを作成する
|
|
215
217
|
- 地理空間データの可視化のために AntV L7 を統合する
|
|
216
218
|
- 3D レンダリングのために React Three Fiber と Drei を使用する
|
|
217
219
|
- `react-three-map` を使用して 3D オブジェクトをマップに対して配置する
|
|
218
220
|
|
|
219
|
-
###
|
|
220
|
-
|
|
221
|
-
MapTiler などのマップサービスを使用するには、環境変数を設定する必要があります。プロジェクトのルートに `.env` ファイルを作成します:
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
PUBLIC_MAPTILER_KEY=your_maptiler_api_key_here
|
|
225
|
-
```
|
|
221
|
+
### 地図のベースマップ
|
|
226
222
|
|
|
227
|
-
|
|
223
|
+
テンプレートは API キー不要の Carto GL スタイル(`src/App.tsx` の `MAP_STYLE_URL`)を既定とします。MapTiler など別プロバイダへ切り替える場合は `mapStyle` を変更し、`.env` / CI で鍵を管理してください。
|
|
228
224
|
|
|
229
225
|
## 🤝 コントリビューション
|
|
230
226
|
|
package/readme/README-RU.md
CHANGED
|
@@ -142,7 +142,8 @@ const latLon = {
|
|
|
142
142
|
latitude: 31.215175,
|
|
143
143
|
longitude: 121.417463,
|
|
144
144
|
};
|
|
145
|
-
const
|
|
145
|
+
const MAP_STYLE_URL
|
|
146
|
+
= "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
146
147
|
|
|
147
148
|
function App() {
|
|
148
149
|
const ref = useRef<HTMLDivElement>(null!);
|
|
@@ -187,7 +188,7 @@ function App() {
|
|
|
187
188
|
zoom: 11,
|
|
188
189
|
pitch: 64.88,
|
|
189
190
|
}}
|
|
190
|
-
mapStyle={
|
|
191
|
+
mapStyle={MAP_STYLE_URL}
|
|
191
192
|
onLoad={initL7}
|
|
192
193
|
>
|
|
193
194
|
<Stats className="stats" parent={ref} />
|
|
@@ -211,20 +212,15 @@ export default App;
|
|
|
211
212
|
```
|
|
212
213
|
|
|
213
214
|
Этот пример демонстрирует:
|
|
215
|
+
|
|
214
216
|
- Создание карты MapLibre GL с помощью `react-map-gl`
|
|
215
217
|
- Интеграция AntV L7 для визуализации геопространственных данных
|
|
216
218
|
- Использование React Three Fiber и Drei для 3D-рендеринга
|
|
217
219
|
- Позиционирование 3D-объектов относительно карты с помощью `react-three-map`
|
|
218
220
|
|
|
219
|
-
###
|
|
220
|
-
|
|
221
|
-
Для использования сервисов карт, таких как MapTiler, вам нужно настроить переменные окружения. Создайте файл `.env` в корне вашего проекта:
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
PUBLIC_MAPTILER_KEY=your_maptiler_api_key_here
|
|
225
|
-
```
|
|
221
|
+
### Подложка карты
|
|
226
222
|
|
|
227
|
-
|
|
223
|
+
В шаблоне по умолчанию используется стиль Carto GL без API-ключа (`MAP_STYLE_URL` в `src/App.tsx`). Для другого провайдера (например, MapTiler) задайте `mapStyle` и храните ключи в `.env` / CI.
|
|
228
224
|
|
|
229
225
|
## 🤝 Участие в разработке
|
|
230
226
|
|
package/rsbuild.config.ts
CHANGED
|
@@ -1,11 +1,39 @@
|
|
|
1
|
+
import process from "node:process";
|
|
1
2
|
import { defineConfig, loadEnv } from "@rsbuild/core";
|
|
3
|
+
import { pluginLess } from "@rsbuild/plugin-less";
|
|
2
4
|
import { pluginReact } from "@rsbuild/plugin-react";
|
|
5
|
+
import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin";
|
|
3
6
|
import tailwind from "@tailwindcss/postcss";
|
|
7
|
+
import TurboConsole from "unplugin-turbo-console/rspack";
|
|
4
8
|
|
|
5
9
|
const { publicVars } = loadEnv({ cwd: "./environments" });
|
|
6
10
|
|
|
11
|
+
function normalizeBasePath(): string {
|
|
12
|
+
const raw = process.env.BASE_PATH?.trim();
|
|
13
|
+
if (!raw || raw === "/") {
|
|
14
|
+
return "/";
|
|
15
|
+
}
|
|
16
|
+
const prefixed = raw.startsWith("/") ? raw : `/${raw}`;
|
|
17
|
+
return prefixed.endsWith("/") ? prefixed : `${prefixed}/`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const basePath = normalizeBasePath();
|
|
21
|
+
const useSubpath = basePath !== "/";
|
|
22
|
+
|
|
23
|
+
const enableRsdoctor = Boolean(process.env.RSDOCTOR);
|
|
24
|
+
const enableTurboConsole = process.env.NODE_ENV === "development";
|
|
25
|
+
|
|
7
26
|
export default defineConfig({
|
|
8
|
-
|
|
27
|
+
...(useSubpath
|
|
28
|
+
? {
|
|
29
|
+
server: { base: basePath },
|
|
30
|
+
output: { assetPrefix: basePath },
|
|
31
|
+
}
|
|
32
|
+
: {}),
|
|
33
|
+
performance: {
|
|
34
|
+
...(enableRsdoctor ? { buildCache: false } : {}),
|
|
35
|
+
},
|
|
36
|
+
plugins: [pluginReact(), pluginLess()],
|
|
9
37
|
source: {
|
|
10
38
|
define: publicVars,
|
|
11
39
|
},
|
|
@@ -15,5 +43,24 @@ export default defineConfig({
|
|
|
15
43
|
plugins: [tailwind],
|
|
16
44
|
},
|
|
17
45
|
},
|
|
46
|
+
rspack: [
|
|
47
|
+
(config) => {
|
|
48
|
+
if (enableTurboConsole) {
|
|
49
|
+
config.plugins.push(TurboConsole());
|
|
50
|
+
}
|
|
51
|
+
if (enableRsdoctor) {
|
|
52
|
+
config.plugins.push(
|
|
53
|
+
new RsdoctorRspackPlugin({
|
|
54
|
+
output: {
|
|
55
|
+
mode: "brief",
|
|
56
|
+
options: {
|
|
57
|
+
type: ["json"],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
],
|
|
18
65
|
},
|
|
19
66
|
});
|
package/src/App.tsx
CHANGED
|
@@ -23,7 +23,53 @@ const latLon = {
|
|
|
23
23
|
latitude: 31.215175,
|
|
24
24
|
longitude: 121.417463,
|
|
25
25
|
};
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
/** Carto 托管的 MapLibre GL 矢量底图,无需 API Key(使用请遵守 https://carto.com/basemaps/ 条款)。 */
|
|
28
|
+
const MAP_STYLE_URL = "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
|
|
29
|
+
|
|
30
|
+
function publicAssetUrl(filename: string): string {
|
|
31
|
+
const base = (import.meta.env.BASE_URL ?? "/").replace(/\/$/, "");
|
|
32
|
+
const path = filename.startsWith("/") ? filename : `/${filename}`;
|
|
33
|
+
return `${base || ""}${path}`.replaceAll("//", "/");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const HOMEPAGE = "https://github.com/Trapar-waves/react-three-maplibre";
|
|
37
|
+
const LOGOS_SET_URL = "https://icon-sets.iconify.design/logos/";
|
|
38
|
+
|
|
39
|
+
interface TechPill {
|
|
40
|
+
id: string;
|
|
41
|
+
label: string;
|
|
42
|
+
iconClass: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const techStack: TechPill[] = [
|
|
46
|
+
{ id: "react", label: "React 19", iconClass: "icon-[logos--react]" },
|
|
47
|
+
{ id: "ts", label: "TypeScript", iconClass: "icon-[logos--typescript-icon]" },
|
|
48
|
+
{ id: "tailwind", label: "Tailwind 4", iconClass: "icon-[logos--tailwindcss-icon]" },
|
|
49
|
+
{ id: "rsbuild", label: "Rsbuild", iconClass: "icon-[material-icon-theme--rstack]" },
|
|
50
|
+
{ id: "maplibre", label: "MapLibre · react-map-gl", iconClass: "icon-[simple-icons--maplibre]" },
|
|
51
|
+
{ id: "l7", label: "AntV L7", iconClass: "icon-[logos--markdown]" },
|
|
52
|
+
{ id: "r3f", label: "R3F · drei · three-stdlib", iconClass: "icon-[logos--threejs]" },
|
|
53
|
+
{ id: "rtmap", label: "react-three-map", iconClass: "icon-[logos--markdown]" },
|
|
54
|
+
{ id: "eslint", label: "ESLint", iconClass: "icon-[logos--eslint]" },
|
|
55
|
+
{ id: "pnpm", label: "pnpm", iconClass: "icon-[logos--pnpm]" },
|
|
56
|
+
{ id: "github", label: "GitHub Actions", iconClass: "icon-[logos--github-icon]" },
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const readmeFeatures: string[] = [
|
|
60
|
+
"MapLibre 与 AntV L7 组合,自定义地图与点层渲染。",
|
|
61
|
+
"@react-three/fiber、drei 将 Three.js 以声明式接入 React。",
|
|
62
|
+
"react-three-map 与 MapLibre 视口同步;Canvas 使用 overlay 模式使 Three 叠在 L7 点层之上。",
|
|
63
|
+
"Tailwind CSS 快速布局与面板样式。",
|
|
64
|
+
"TypeScript 覆盖地图与场景相关类型。",
|
|
65
|
+
"Rsbuild 开发与生产构建。",
|
|
66
|
+
"react-map-gl 提供交互与导航体验。",
|
|
67
|
+
"three-stdlib 与 drei 复用常用几何与调试组件。",
|
|
68
|
+
"GitHub Pages 支持 BASE_PATH 与 404.html SPA 部署。",
|
|
69
|
+
"默认 Carto Basemaps GL 样式,本地与 CI 均无需地图 API Key。",
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const readmeTechNote = "演示使用 @react-three/drei 的 Stats;生产可按需移除。若需其他底图,可在 App.tsx 中替换 MAP_STYLE_URL 并自行处理鉴权。";
|
|
27
73
|
|
|
28
74
|
function App() {
|
|
29
75
|
const ref = useRef<HTMLDivElement>(null!);
|
|
@@ -37,8 +83,8 @@ function App() {
|
|
|
37
83
|
}),
|
|
38
84
|
});
|
|
39
85
|
scene.on("loaded", () => {
|
|
40
|
-
fetch("
|
|
41
|
-
.then(res => res.text())
|
|
86
|
+
fetch(publicAssetUrl("BElVQFEFvpAKzddxFZxJ.txt"))
|
|
87
|
+
.then(res => (res.ok ? res.text() : Promise.reject(new Error(String(res.status)))))
|
|
42
88
|
.then((data) => {
|
|
43
89
|
const pointLayer = new PointLayer({
|
|
44
90
|
blend: "additive",
|
|
@@ -54,12 +100,80 @@ function App() {
|
|
|
54
100
|
.color("#080298");
|
|
55
101
|
|
|
56
102
|
scene.addLayer(pointLayer);
|
|
57
|
-
})
|
|
103
|
+
})
|
|
104
|
+
.catch(() => {});
|
|
58
105
|
});
|
|
59
106
|
}
|
|
60
107
|
}
|
|
61
108
|
return (
|
|
62
109
|
<div className="h-screen w-screen relative overflow-hidden" ref={ref}>
|
|
110
|
+
<aside
|
|
111
|
+
className="pointer-events-none absolute left-4 top-4 z-10 max-w-sm motion-safe:transition motion-safe:duration-200"
|
|
112
|
+
aria-label="模板说明"
|
|
113
|
+
>
|
|
114
|
+
<div
|
|
115
|
+
className="pointer-events-auto max-h-[min(70vh,560px)] overflow-y-auto overscroll-contain rounded-xl border border-white/15 bg-slate-950/80 p-4 text-sm text-slate-100 shadow-xl backdrop-blur-md"
|
|
116
|
+
>
|
|
117
|
+
<p className="font-semibold text-white">react-three-maplibre</p>
|
|
118
|
+
<p className="mt-2 leading-relaxed text-slate-300">
|
|
119
|
+
MapLibre 与 react-three-map 同屏;L7 点层叠加 CSV,Three 方体经
|
|
120
|
+
{" "}
|
|
121
|
+
<code className="rounded bg-slate-800 px-1">overlay</code>
|
|
122
|
+
{" "}
|
|
123
|
+
画布叠在 L7 之上。底图为 Carto 公开 GL 样式,无需地图服务 API Key。技术图标见
|
|
124
|
+
{" "}
|
|
125
|
+
<a
|
|
126
|
+
href={LOGOS_SET_URL}
|
|
127
|
+
className="font-medium text-sky-300 underline decoration-sky-700 underline-offset-2 hover:text-sky-200"
|
|
128
|
+
target="_blank"
|
|
129
|
+
rel="noreferrer"
|
|
130
|
+
>
|
|
131
|
+
Iconify logos
|
|
132
|
+
</a>
|
|
133
|
+
。
|
|
134
|
+
</p>
|
|
135
|
+
<p className="mt-3 text-xs font-medium uppercase tracking-wide text-slate-500">
|
|
136
|
+
技术栈
|
|
137
|
+
</p>
|
|
138
|
+
<div className="mt-2 flex flex-wrap gap-2">
|
|
139
|
+
{techStack.map(item => (
|
|
140
|
+
<span
|
|
141
|
+
key={item.id}
|
|
142
|
+
className="inline-flex items-center gap-1.5 rounded-lg border border-white/10 bg-slate-900/80 px-2 py-1 text-xs text-slate-200"
|
|
143
|
+
>
|
|
144
|
+
<span className={`${item.iconClass} text-base text-sky-300`} aria-hidden />
|
|
145
|
+
{item.label}
|
|
146
|
+
</span>
|
|
147
|
+
))}
|
|
148
|
+
</div>
|
|
149
|
+
<p className="mt-4 text-xs font-medium uppercase tracking-wide text-slate-500">
|
|
150
|
+
README 摘要
|
|
151
|
+
</p>
|
|
152
|
+
<ul className="mt-2 list-disc space-y-1 pl-4 text-slate-400">
|
|
153
|
+
{readmeFeatures.map(line => (
|
|
154
|
+
<li key={line}>{line}</li>
|
|
155
|
+
))}
|
|
156
|
+
</ul>
|
|
157
|
+
<p className="mt-3 text-xs italic leading-relaxed text-slate-500">
|
|
158
|
+
{readmeTechNote}
|
|
159
|
+
</p>
|
|
160
|
+
<p className="mt-3 text-xs leading-relaxed text-slate-500">
|
|
161
|
+
品牌图标来自
|
|
162
|
+
{" "}
|
|
163
|
+
<a href={LOGOS_SET_URL} className="text-sky-400 underline hover:text-sky-300" target="_blank" rel="noreferrer">SVG Logos</a>
|
|
164
|
+
{" "}
|
|
165
|
+
(CC0)。
|
|
166
|
+
</p>
|
|
167
|
+
<a
|
|
168
|
+
href={HOMEPAGE}
|
|
169
|
+
className="mt-3 inline-flex min-h-11 w-full items-center justify-center rounded-lg bg-sky-500 px-4 py-2 text-sm font-semibold text-slate-950 hover:bg-sky-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
|
|
170
|
+
target="_blank"
|
|
171
|
+
rel="noreferrer"
|
|
172
|
+
>
|
|
173
|
+
查看仓库
|
|
174
|
+
</a>
|
|
175
|
+
</div>
|
|
176
|
+
</aside>
|
|
63
177
|
<Map
|
|
64
178
|
id="map"
|
|
65
179
|
ref={mapRef}
|
|
@@ -68,12 +182,16 @@ function App() {
|
|
|
68
182
|
zoom: 11,
|
|
69
183
|
pitch: 64.88,
|
|
70
184
|
}}
|
|
71
|
-
mapStyle={
|
|
185
|
+
mapStyle={MAP_STYLE_URL}
|
|
72
186
|
onLoad={initL7}
|
|
73
187
|
>
|
|
74
188
|
<Stats className="stats" parent={ref} />
|
|
75
189
|
|
|
76
|
-
<Canvas
|
|
190
|
+
<Canvas
|
|
191
|
+
overlay
|
|
192
|
+
id="trapar-r3f-overlay"
|
|
193
|
+
{...latLon}
|
|
194
|
+
>
|
|
77
195
|
<hemisphereLight
|
|
78
196
|
args={["#ffffff", "#60666C"]}
|
|
79
197
|
position={[1, 4.5, 3]}
|