在vite创建的vue3项目中使用Cesium标记地点(基于加载建筑样式,划分区域)
-
使用vite创建vue3项目
npm create vite@latest
cd到创建的项目文件夹中
npm install
安装Cesium
npm i cesium vite-plugin-cesium vite -D
-
配置
-
vite.config.js文件:添加Cesium并设置反向代理实现跨域。
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import cesium from 'vite-plugin-cesium'; export default defineConfig({ plugins: [vue(), cesium()], //设置反向代理,跨域 server: { proxy: { '/ArcGIS': { target: 'https://services.arcgisonline.com',//代理的地址 changeOrigin: true, } } } });
-
style.css(可选):修改#app样式
#app { max-width: 100%; margin: 0 auto; padding: 2rem; text-align: center; }
-
-
代码
-
App.vue
<template> <div id="cesiumContainer"></div> </template> <script setup> import * as Cesium from 'cesium'; import { onMounted } from 'vue'; onMounted(async () => { // 相当于密钥,申请使用下边链接中的数据时需要用到 Cesium.Ion.defaultAccessToken = '你的token'; Cesium.ArcGisMapService.defaultAccessToken = '你的token'; let viewer = new Cesium.Viewer('cesiumContainer', { // 防止报错 infoBox: false, // 去掉右上角的一个小选项卡 baseLayerPicker: false, // 加载世界街道地图的底图 baseLayer: Cesium.ImageryLayer.fromProviderAsync( Cesium.ArcGisMapServerImageryProvider.fromUrl("/ArcGIS/rest/services/World_Street_Map/MapServer") ), // 三维立体效果、水波纹 terrainProvider: await Cesium.createWorldTerrainAsync({ requestVertexNormals: true, requestWaterMask: true }) }); viewer.camera.setView({ // 初始的相机的定位 定在纽约 destination: new Cesium.Cartesian3(1332761, -4662399, 4137888), // 方向 俯仰 orientation: { heading: 0.6, pitch: -0.66 } }); // 添加纽约建筑模型 let city = viewer.scene.primitives.add( await Cesium.Cesium3DTileset.fromIonAssetId(75343) ); // 定义建筑的3D样式 层次分明 city.style = new Cesium.Cesium3DTileStyle({ color: { // 条件判断建筑具体的颜色 conditions: [ ['${Height} >= 300', 'rgba(45,0,75,0.5)'], ['${Height} >= 200', 'rgb(102,71,151)'], ['${Height} >= 100', 'rgba(170,162,204,0.5)'], ['${Height} >= 50', 'rgba(224,226,238,0.5)'], ['${Height} >= 25', 'rgba(252,230,200,0.5)'], ['${Height} >= 10', 'rgba(248,176,87,0.5)'], ["true", 'rgb(127,59,8)'] ] } }) // 邻域边界的加载 let neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./assets/SampleData/sampleNeighborhoods.geojson'); // 贴在地图表面 neighborhoodsPromise.then((dataSource) => { // 将数据添加到查看器 viewer.dataSources.add(dataSource); // 把数据进行着色的调整以及放到地图的表面 // 拿到区域的实例 Get the array of entities let neighborhoodsEntities = dataSource.entities.values; for (let i = 0; i < neighborhoodsEntities.length; i++) { let entity = neighborhoodsEntities[i]; // 判断存不存在相应的图形 if (Cesium.defined(entity.polygon)) { entity.name = entity.properties.neighborhood; // 设置多边形颜色 entity.polygon.material = Cesium.Color.fromRandom({ red: 0.1, maximumGreen: 0.5, minimumBlue: 0.5, alpha: 0.6 }); // 设置地形着色 entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN; // 设置位置 贴到多边形最底下 let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions; entity.position = Cesium.Ellipsoid.WGS84.scaleToGeocentricSurface( Cesium.BoundingSphere.fromPoints(polyPositions).center ); // 生成标签 entity.label = { text: entity.name, showBackground: true, scale: 0.6, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 设置显示的距离范围 distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10, 8000), // 禁用的距离 disableDepthTestDistance: 100 } } } }); // 地图标记显示 let kmloptions = { camera: viewer.scene.camera, canvas: viewer.scene.canvas, // 如果我们想要将几何特征(多边形、线串和线性环)固定在地面上,则为true clampToGround: true }; // KML文件时谷歌公司创建的一个地标性文件,用于记录某一地点、或者连续地点的时间、经纬度、海拔等地理信息数据 let geoCachePromise = Cesium.KmlDataSource.load('./assets/SampleData/sampleGeocacheLocations.kml', kmloptions); // 将geocache广告牌实体添加到场景中并为其设置样式 geoCachePromise.then((dataSource) => { // console.log(dataSource) // 将新数据作为实体添加到查看器 viewer.dataSources.add(dataSource); // 获取实体数组 let geoCacheEntities = dataSource.entities.values; for (let i = 0; i < geoCacheEntities.length; i++) { let entity = geoCacheEntities[i]; if (Cesium.defined(entity.billboard)) { // 调整垂直原点,使图钉位于地形上 entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM; entity.billboard.image = '/assets/tagpark.png'; // 禁用标签以减少混乱 entity.label = undefined; // 添加距离现实条件 entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10, 20000); // 以度为单位计算经度和纬度 let cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now())); // 这地方的cartographicPosition.longitude,我当时报错了,我是直接敲完cartographicPosition之后,把前边的let longtitide中的longtitude直接复制过来的,这好像不行,就老老实实的敲上就行,或者敲完lon,出来提示之后选longtitude。 let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude); let longtitude = Cesium.Math.toDegrees(cartographicPosition.longitude); // 修改描述 let description = '<table class="Cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' + '<tr><th>' + "longtitude" + '</th><td>' + longtitude.toFixed(5) + '</td><tr>' + '<tr><th>' + "latitude" + '</th><td>' + latitude.toFixed(5) + '</td><tr>' + '<tr><th>' + "实时人流" + '</th><td>' + Math.floor(Math.random() * 20000) + '</td><tr>' + '<tr><th>' + "安全等级" + '</th><td>' + Math.floor(Math.random() * 5) + '</td><tr>' + '</tbody><table>'; entity.description = description; } } }) }) </script> <style> html, body, #app, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } </style>
-
解读
-
加载token
// 相当于密钥,申请使用下边链接中的数据时需要用到 Cesium.Ion.defaultAccessToken = '你的token'; Cesium.ArcGisMapService.defaultAccessToken = '你的token';
-
创建查看器viewer,加载世界街道地图,注意vite.config.js中配合的跨域。
let viewer = new Cesium.Viewer('cesiumContainer', { // 防止报错 infoBox: false, // 去掉右上角的一个小选项卡 baseLayerPicker: false, // 加载世界街道地图的底图 baseLayer: Cesium.ImageryLayer.fromProviderAsync( Cesium.ArcGisMapServerImageryProvider.fromUrl("/ArcGIS/rest/services/World_Street_Map/MapServer") ), // 三维立体效果、水波纹 terrainProvider: await Cesium.createWorldTerrainAsync({ requestVertexNormals: true, requestWaterMask: true }) });
-
初始化相机位置
viewer.camera.setView({ // 初始的相机的定位 定在纽约 destination: new Cesium.Cartesian3(1332761, -4662399, 4137888), // 方向 俯仰 orientation: { heading: 0.6, pitch: -0.66 } });
-
添加纽约建筑模型并设置建筑颜色样式
// 添加纽约建筑模型 let city = viewer.scene.primitives.add( await Cesium.Cesium3DTileset.fromIonAssetId(75343) ); // 定义建筑的3D样式 层次分明 city.style = new Cesium.Cesium3DTileStyle({ color: { // 条件判断建筑具体的颜色 conditions: [ ['${Height} >= 300', 'rgba(45,0,75,0.5)'], ['${Height} >= 200', 'rgb(102,71,151)'], ['${Height} >= 100', 'rgba(170,162,204,0.5)'], ['${Height} >= 50', 'rgba(224,226,238,0.5)'], ['${Height} >= 25', 'rgba(252,230,200,0.5)'], ['${Height} >= 10', 'rgba(248,176,87,0.5)'], ["true", 'rgb(127,59,8)'] ] } })
-
划分城市区域并着色,下边用到的地图标记文件也在里边,区域文件 提取码:99jq
// 邻域边界的加载 let neighborhoodsPromise = Cesium.GeoJsonDataSource.load('./assets/SampleData/sampleNeighborhoods.geojson'); // 贴在地图表面 neighborhoodsPromise.then((dataSource) => { // 将数据添加到查看器 viewer.dataSources.add(dataSource); // 把数据进行着色的调整以及放到地图的表面 // 拿到区域的实例 Get the array of entities let neighborhoodsEntities = dataSource.entities.values; for (let i = 0; i < neighborhoodsEntities.length; i++) { let entity = neighborhoodsEntities[i]; // 判断存不存在相应的图形 if (Cesium.defined(entity.polygon)) { entity.name = entity.properties.neighborhood; // 设置多边形颜色 entity.polygon.material = Cesium.Color.fromRandom({ red: 0.1, maximumGreen: 0.5, minimumBlue: 0.5, alpha: 0.6 }); // 设置地形着色 entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN; // 设置位置 贴到多边形最底下 let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions; entity.position = Cesium.Ellipsoid.WGS84.scaleToGeocentricSurface( Cesium.BoundingSphere.fromPoints(polyPositions).center ); // 生成标签 entity.label = { text: entity.name, showBackground: true, scale: 0.6, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 设置显示的距离范围 distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10, 8000), // 禁用的距离 disableDepthTestDistance: 100 } } } })
-
利用KML文件实现在地图上标记地点
// 地图标记显示 let kmloptions = { camera: viewer.scene.camera, canvas: viewer.scene.canvas, // 如果我们想要将几何特征(多边形、线串和线性环)固定在地面上,则为true clampToGround: true }; // KML文件时谷歌公司创建的一个地标性文件,用于记录某一地点、或者连续地点的时间、经纬度、海拔等地理信息数据 let geoCachePromise = Cesium.KmlDataSource.load('./assets/SampleData/sampleGeocacheLocations.kml', kmloptions); // 将geocache广告牌实体添加到场景中并为其设置样式 geoCachePromise.then((dataSource) => { // console.log(dataSource) // 将新数据作为实体添加到查看器 viewer.dataSources.add(dataSource); // 获取实体数组 let geoCacheEntities = dataSource.entities.values; for (let i = 0; i < geoCacheEntities.length; i++) { let entity = geoCacheEntities[i]; if (Cesium.defined(entity.billboard)) { // 调整垂直原点,使图钉位于地形上 entity.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM; entity.billboard.image = '/assets/tagpark.png'; // 禁用标签以减少混乱 entity.label = undefined; // 添加距离现实条件 entity.billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10, 20000); // 以度为单位计算经度和纬度 let cartographicPosition = Cesium.Cartographic.fromCartesian(entity.position.getValue(Cesium.JulianDate.now())); let latitude = Cesium.Math.toDegrees(cartographicPosition.latitude); let longtitude = Cesium.Math.toDegrees(cartographicPosition.longitude); // 修改描述 let description = '<table class="Cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' + '<tr><th>' + "longtitude" + '</th><td>' + longtitude.toFixed(5) + '</td><tr>' + '<tr><th>' + "latitude" + '</th><td>' + latitude.toFixed(5) + '</td><tr>' + '<tr><th>' + "实时人流" + '</th><td>' + Math.floor(Math.random() * 20000) + '</td><tr>' + '<tr><th>' + "安全等级" + '</th><td>' + Math.floor(Math.random() * 5) + '</td><tr>' + '</tbody><table>'; entity.description = description; } } })
-
-
-
效果:npm run dev 运行