Skip to content

Commit 0d9e719

Browse files
Merge pull request #1 from wujighostking/develop
Develop
2 parents 94538e8 + 471681e commit 0d9e719

File tree

402 files changed

+7696
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

402 files changed

+7696
-4
lines changed

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export default defineConfig({
44
formatters: true,
55
unocss: true,
66
vue: true,
7+
ignores: ['public/cesium/**/*.*'],
78
})

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"postinstall": "nuxt prepare"
2323
},
2424
"dependencies": {
25+
"cesium": "^1.135.0",
2526
"vue": "^3.5.24",
2627
"vue-router": "^4.6.3"
2728
},
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<script setup lang="ts">
2+
import type { Viewer } from 'cesium'
3+
import { useGLTF } from '#imports'
4+
import { Cartesian3, Color, HeightReference, Math, PolygonHierarchy } from 'cesium'
5+
6+
const cesiumContainerRef = useTemplateRef('cesiumContainer')
7+
8+
let viewer: Viewer
9+
10+
onMounted(() => {
11+
if (!cesiumContainerRef.value)
12+
return
13+
14+
viewer = useViewer(cesiumContainerRef.value)
15+
16+
// 加载泰山区宿舍的GeoJSON数据
17+
const data = loadGeoJson('/data/泰山区宿舍.geojson', {
18+
stroke: Color.fromCssColorString('#aaaa9d'),
19+
fill: Color.fromCssColorString('#aaaa9d').withAlpha(0.5),
20+
strokeWidth: 3,
21+
clampToGround: true,
22+
})
23+
viewer.dataSources.add(data)
24+
25+
geoJsonToBuildingModel('/data/泰山区宿舍1-4.geojson').then((positions) => {
26+
positions.forEach((position) => {
27+
viewer.entities.add({
28+
polygon: {
29+
hierarchy: new PolygonHierarchy(position), // 底面形状
30+
height: 0, // 底部高度(从地面0开始)
31+
heightReference: HeightReference.CLAMP_TO_TERRAIN,
32+
extrudedHeight: 30, // 顶部高度(总高度100米,可调整)
33+
material: Color.WHITE, // 填充材质(半透明红色)
34+
outline: true, // 显示轮廓
35+
outlineColor: Color.BLACK, // 轮廓颜色
36+
outlineWidth: 2, // 轮廓宽度
37+
},
38+
})
39+
})
40+
})
41+
42+
useGLTF('/data/Air.glb', { position: Cartesian3.fromDegrees(113.36629986763, 23.15732289356693, 3) })
43+
44+
viewer.camera.flyTo({
45+
destination: Cartesian3.fromDegrees(113.36629986763, 23.15732289356693, 70),
46+
orientation: {
47+
heading: Math.toRadians(-90),
48+
pitch: 0,
49+
},
50+
})
51+
})
52+
53+
onUnmounted(() => {
54+
if (viewer) {
55+
viewer.destroy()
56+
}
57+
})
58+
</script>
59+
60+
<template>
61+
<div>
62+
<div ref="cesiumContainer" style="width: 100%;height: 100vh;" />
63+
</div>
64+
</template>
65+
66+
<style scoped>
67+
68+
</style>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { Cartesian3 } from 'cesium'
2+
import { useViewer } from '~/composables/useViewer'
3+
4+
export function useGLTF(uri: string, options: { position: Cartesian3 }) {
5+
const { position } = options
6+
const viewer = useViewer()
7+
8+
viewer.entities.add({
9+
position,
10+
model: {
11+
uri,
12+
13+
// minimumPixelSize: 64,
14+
// maximumScale: 10,
15+
// scale: 1.0,
16+
},
17+
})
18+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ImageryLayer, OpenStreetMapImageryProvider, Viewer } from 'cesium'
2+
3+
// eslint-disable-next-line import/no-mutable-exports
4+
export let viewer: Viewer
5+
6+
export function useViewer(container?: HTMLDivElement) {
7+
if (viewer) {
8+
return viewer
9+
}
10+
viewer = new Viewer(container!, {
11+
geocoder: false,
12+
homeButton: false,
13+
sceneModePicker: false,
14+
baseLayerPicker: false,
15+
navigationHelpButton: false,
16+
17+
animation: false,
18+
timeline: false,
19+
creditContainer: document.createElement('div'),
20+
fullscreenButton: false,
21+
22+
infoBox: false,
23+
24+
baseLayer: new ImageryLayer(new OpenStreetMapImageryProvider({
25+
url: 'https://tile.openstreetmap.org/',
26+
})),
27+
// terrain: Terrain.fromWorldTerrain(),
28+
})
29+
30+
const cameraController = viewer.scene.screenSpaceCameraController
31+
cameraController.minimumZoomDistance = 3
32+
cameraController.maximumZoomDistance = 600
33+
34+
// 摄像机不能进入地下
35+
viewer.scene.globe.depthTestAgainstTerrain = true
36+
37+
return viewer
38+
}

packages/app/pages/index.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
<script setup lang="ts">
2-
2+
import CesiumViewer from '~/components/CesiumViewer.vue'
33
</script>
44

55
<template>
6-
<div>app</div>
6+
<div>
7+
<CesiumViewer />
8+
</div>
79
</template>
810

9-
<style scoped>
10-
11+
<style>
12+
html,
13+
body {
14+
margin: 0;
15+
padding: 0;
16+
}
1117
</style>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import 'cesium/Build/Cesium/Widgets/widgets.css'
2+
3+
export default defineNuxtPlugin({
4+
name: 'nuxt-plugin-cesium',
5+
enforce: 'pre',
6+
hooks: {
7+
'app:beforeMount': function () {
8+
;(window as any).CESIUM_BASE_URL = '/cesium/'
9+
},
10+
11+
},
12+
env: {
13+
// 如果不希望插件在渲染仅服务端或岛式组件时运行,将此值设置为 `false`
14+
islands: false,
15+
},
16+
})

packages/app/utils/loadGeoJson.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Cartesian3, GeoJsonDataSource } from 'cesium'
2+
import { EMPTY_OBJ, isFunction } from '~~/packages/shared/utils'
3+
4+
interface Options extends GeoJsonDataSource.LoadOptions {
5+
beforeLoad?: () => void
6+
afterLoaded?: (data: any) => void
7+
}
8+
9+
export function loadGeoJson(url: string, options?: Options) {
10+
const { beforeLoad, afterLoaded } = options ?? EMPTY_OBJ
11+
12+
if (isFunction(beforeLoad)) {
13+
beforeLoad()
14+
}
15+
16+
const geoJsonPending = GeoJsonDataSource.load(url, options)
17+
18+
return geoJsonPending.then((data) => {
19+
if (isFunction(afterLoaded)) {
20+
afterLoaded(data)
21+
}
22+
23+
return data
24+
})
25+
}
26+
27+
export async function geoJsonToBuildingModel(url: string) {
28+
const geojsonData = await (await fetch(url)).json()
29+
30+
let positions: Cartesian3[][] = []
31+
32+
// 解析GeoJSON并生成多面体(棱柱)
33+
geojsonData?.features?.forEach?.((feature: any) => {
34+
const geometry = feature.geometry
35+
if (geometry.type === 'Polygon') {
36+
positions = geometry.coordinates.map((coordinates: [number, number][]) => {
37+
return coordinates.map((coord: [number, number]) => {
38+
const longitude = coord[0] // 经度
39+
const latitude = coord[1] // 纬度
40+
return Cartesian3.fromDegrees(longitude, latitude)
41+
})
42+
})
43+
}
44+
})
45+
46+
return positions
47+
}

packages/shared/utils/cancel.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { LOOP } from './constants'
2+
3+
export function cancelPromise(callback: (...args: any[]) => any) {
4+
let cancel = LOOP
5+
6+
const promise = new Promise((resolve, reject) => {
7+
cancel()
8+
cancel = () => {
9+
resolve = reject = LOOP
10+
}
11+
12+
try {
13+
const maybePromiseOrResult = callback()
14+
15+
if (maybePromiseOrResult instanceof Promise) {
16+
maybePromiseOrResult.then((result) => {
17+
resolve(result)
18+
}).catch((error) => {
19+
reject(error)
20+
})
21+
}
22+
else {
23+
resolve(maybePromiseOrResult)
24+
}
25+
}
26+
catch (error) {
27+
reject(error)
28+
}
29+
})
30+
31+
return {
32+
cancel,
33+
promise,
34+
}
35+
}

packages/shared/utils/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const EMPTY_OBJ = Object.create(null)
2+
3+
// eslint-disable-next-line antfu/top-level-function
4+
export const LOOP = () => {}

0 commit comments

Comments
 (0)