一、vue-cesium官网地址:A Vue 3 based component library of CesiumJS for developers | Vue for Cesium
二、安装
npm install vue-cesium --save
三、main.ts中引入使用
import VueCesium from 'vue-cesium'
app.use(VueCesium, {
cesiumPath: "/Cesium/Cesium.js",
});
四、准备好数据文件
五、编写代码
1、加载建筑物
<vc-viewer ref="viewerRef" @ready="onViewerReady">
<!-- 加载建筑物 -->
<vc-primitive-tileset
ref="primitive"
:url="'wuhuBuildingsTest6/test6/tileset.json'"
@ready="tilesetOnReady($event, 'building')"
>
</vc-primitive-tileset>
</vc-viewer>
const onViewerReady = async ({
Cesium,
viewer,
cesiumObject: _cesiumObject,
}: VcReadyObject) => {
emmiter.emit("map3dReady");
viewer.scene.globe.translucency.enabled = true; // 允许地表透明
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(118.381467, 31.320145, 500.0), // 设置位置
orientation: {
heading: Cesium.Math.toRadians(-5),
pitch: Cesium.Math.toRadians(-22),
roll: 0,
},
});
addLayer(viewer); //暗色地图
initRiver(Cesium); //河流
viewer.dataSources.add(await createRoadLine(roads)); //道路
// 开启抗锯齿
// @ts-ignore
if (Cesium.FeatureDetection?.supportsImageRenderingPixelated()) {
viewer.resolutionScale = window.devicePixelRatio;
}
viewer.scene.postProcessStages.fxaa.enabled = true;
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 150; //相机的高度的最小值
};
const addLayer = async (viewer: Cesium.Viewer) => {
const MapLayers = [
{
name: "高德暗色底图",
iconUrl: "http://mars3d.cn/img/basemaps/blackMarble.png",
url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
maximumLevel: 18,
minimumLevel: 4,
},
];
const imageryViewModels = MapLayers.map(
({ name, iconUrl, maximumLevel, minimumLevel = 4, url }) => {
return new Cesium.ProviderViewModel({
name,
iconUrl,
creationFunction: function () {
const layer = new Cesium.UrlTemplateImageryProvider({
url,
maximumLevel,
minimumLevel,
});
return layer;
},
tooltip: "",
});
}
);
const baseLayerPickerContainer = document.querySelector(
".cesium-viewer-toolbar"
)!;
const baseLayerPicker = new Cesium.BaseLayerPicker(baseLayerPickerContainer, {
globe: viewer.scene.globe,
imageryProviderViewModels: imageryViewModels,
});
// 设置默认底图
baseLayerPicker.viewModel.selectedImagery = imageryViewModels[0];
const baseLayer = viewer.imageryLayers.get(0);
modifyMap(
baseLayer,
{
filterRGB: [78, 112, 166],
invertColor: true,
},
// @ts-ignore
viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources
);
};
//建筑物颜色
const tilesetOnReady = (
{ Cesium, viewer, cesiumObject: _cesiumObject }: VcReadyObject,
type: string
) => {
const cesiumObject = _cesiumObject as Cesium.Cesium3DTileset;
switch (type) {
case "building":
viewer.infoBox.destroy();
buildingColor(cesiumObject, "building");
break;
default:
return;
}
};
const buildingColor = function (
cesiumObject: Cesium.Cesium3DTileset,
type: string
) {
if (Array.isArray(cesiumObject) || !cesiumObject) return;
// @ts-ignore
cesiumObject.enableModelExperimental = true;
let temp;
switch (type) {
case "building":
temp = buildingShader;
break;
default:
return;
}
cesiumObject.customShader = new Cesium.CustomShader({
lightingModel: Cesium.LightingModel.UNLIT,
varyings: {
v_normalMC: Cesium.VaryingType.VEC3,
},
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
v_normalMC = vsInput.attributes.normalMC;
}
`,
fragmentShaderText: temp,
});
};
2、加载河流
<template v-for="item in riverArray">
<vc-primitive :appearance="riverAppearance">
<vc-geometry-instance :id="item.properties">
<vc-geometry-polygon
:polygonHierarchy="item.coordinate"
:vertexFormat="riverVertexFormat"
:height="10"
></vc-geometry-polygon>
</vc-geometry-instance>
</vc-primitive>
</template>
const viewerRef: any = ref<HTMLElement | null>(null);
onMounted(() => {
viewerRef.value.creatingPromise.then((readyObj: VcReadyObject) => {});
});
//河流
const riverArray = geoJsonToCoordinate(rivers);
const riverAppearance = shallowRef();
const riverVertexFormat = shallowRef();
const initRiver = (Cesium: VcReadyObject["Cesium"]) => {
riverAppearance.value = new Cesium.EllipsoidSurfaceAppearance({
material: new Cesium.Material({
fabric: {
type: "Water",
uniforms: {
normalMap: Cesium.buildModuleUrl("Assets/Textures/waterNormals.jpg"),
frequency: 1000.0,
animationSpeed: 0.05,
amplitude: 10.0,
// 水体颜色
baseWaterColor: Cesium.Color.DODGERBLUE,
},
},
}),
});
riverVertexFormat.value = Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT;
};
完整代码
<template>
<div class="map_content">
<vc-viewer ref="viewerRef" @ready="onViewerReady">
<vc-primitive-tileset
ref="primitive"
:url="'wuhuBuildingsTest6/test6/tileset.json'"
@ready="tilesetOnReady($event, 'building')"
>
</vc-primitive-tileset>
<!-- 循环创建河流 -->
<template v-for="item in riverArray">
<vc-primitive :appearance="riverAppearance">
<vc-geometry-instance :id="item.properties">
<vc-geometry-polygon
:polygonHierarchy="item.coordinate"
:vertexFormat="riverVertexFormat"
:height="10"
></vc-geometry-polygon>
</vc-geometry-instance>
</vc-primitive>
</template>
</vc-viewer>
</div>
</template>
<script lang="ts" setup>
import {
VcViewer,
VcPrimitiveTileset,
VcPrimitive,
VcGeometryPolygon,
VcGeometryInstance,
VcOverlayHtml,
} from "vue-cesium";
import type { VcReadyObject } from "vue-cesium/es/utils/types";
import rivers from "@/assets/data/rivers.json";
import roads from "@/assets/data/road.json";
import { ModelUrl } from "@/service/index";
import buildingShader from "@/shaders/building.js";
import { geoJsonToCoordinate } from "@/utils";
import { modifyMap } from "@/utils/filterColor";
import { createRoadLine } from "@/utils/map3d";
import emmiter from "@/mitt";
const viewerRef: any = ref<HTMLElement | null>(null);
onMounted(() => {
viewerRef.value.creatingPromise.then((readyObj: VcReadyObject) => {});
});
//河流
const riverArray = geoJsonToCoordinate(rivers);
const riverAppearance = shallowRef();
const riverVertexFormat = shallowRef();
const initRiver = (Cesium: VcReadyObject["Cesium"]) => {
riverAppearance.value = new Cesium.EllipsoidSurfaceAppearance({
material: new Cesium.Material({
fabric: {
type: "Water",
uniforms: {
normalMap: Cesium.buildModuleUrl("Assets/Textures/waterNormals.jpg"),
frequency: 1000.0,
animationSpeed: 0.05,
amplitude: 10.0,
// 水体颜色
baseWaterColor: Cesium.Color.DODGERBLUE,
},
},
}),
});
riverVertexFormat.value = Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT;
};
const onViewerReady = async ({
Cesium,
viewer,
cesiumObject: _cesiumObject,
}: VcReadyObject) => {
emmiter.emit("map3dReady");
viewer.scene.globe.translucency.enabled = true; // 允许地表透明
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(118.381467, 31.320145, 500.0), // 设置位置
orientation: {
heading: Cesium.Math.toRadians(-5),
pitch: Cesium.Math.toRadians(-22),
roll: 0,
},
});
addLayer(viewer); //暗色地图
initRiver(Cesium); //河流
viewer.dataSources.add(await createRoadLine(roads)); //道路
// 开启抗锯齿
// @ts-ignore
if (Cesium.FeatureDetection?.supportsImageRenderingPixelated()) {
viewer.resolutionScale = window.devicePixelRatio;
}
viewer.scene.postProcessStages.fxaa.enabled = true;
viewer.scene.screenSpaceCameraController.minimumZoomDistance = 150; //相机的高度的最小值
};
const addLayer = async (viewer: Cesium.Viewer) => {
const MapLayers = [
{
name: "高德暗色底图",
iconUrl: "http://mars3d.cn/img/basemaps/blackMarble.png",
url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
maximumLevel: 18,
minimumLevel: 4,
},
];
const imageryViewModels = MapLayers.map(
({ name, iconUrl, maximumLevel, minimumLevel = 4, url }) => {
return new Cesium.ProviderViewModel({
name,
iconUrl,
creationFunction: function () {
const layer = new Cesium.UrlTemplateImageryProvider({
url,
maximumLevel,
minimumLevel,
});
return layer;
},
tooltip: "",
});
}
);
const baseLayerPickerContainer = document.querySelector(
".cesium-viewer-toolbar"
)!;
const baseLayerPicker = new Cesium.BaseLayerPicker(baseLayerPickerContainer, {
globe: viewer.scene.globe,
imageryProviderViewModels: imageryViewModels,
});
// 设置默认底图
baseLayerPicker.viewModel.selectedImagery = imageryViewModels[0];
const baseLayer = viewer.imageryLayers.get(0);
modifyMap(
baseLayer,
{
filterRGB: [78, 112, 166],
invertColor: true,
},
// @ts-ignore
viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources
);
};
//建筑物颜色
const tilesetOnReady = (
{ Cesium, viewer, cesiumObject: _cesiumObject }: VcReadyObject,
type: string
) => {
const cesiumObject = _cesiumObject as Cesium.Cesium3DTileset;
switch (type) {
case "building":
viewer.infoBox.destroy();
buildingColor(cesiumObject, "building");
break;
default:
return;
}
};
const buildingColor = function (
cesiumObject: Cesium.Cesium3DTileset,
type: string
) {
if (Array.isArray(cesiumObject) || !cesiumObject) return;
// @ts-ignore
cesiumObject.enableModelExperimental = true;
let temp;
switch (type) {
case "building":
temp = buildingShader;
break;
default:
return;
}
cesiumObject.customShader = new Cesium.CustomShader({
lightingModel: Cesium.LightingModel.UNLIT,
varyings: {
v_normalMC: Cesium.VaryingType.VEC3,
},
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
v_normalMC = vsInput.attributes.normalMC;
}
`,
fragmentShaderText: temp,
});
};
</script>
效果图: