vue3-浅记录一下vue-cesium的使用-加载建筑物 加载河流 道路闪烁线

该文章介绍了如何使用Vue-Cesium库在Vue3项目中集成CesiumJS,进行3D地图的构建。主要步骤包括安装vue-cesium库,配置main.ts文件,加载数据文件,以及展示建筑物和河流。此外,还涉及到了地图的交互设置,如调整视角、添加图层、自定义建筑物颜色和水面效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、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>

效果图:

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值