简单点说,三维地图可视化,就是将地理数据转换成三维立体的可视化形态,通过将具有地域特征的数据,或者数据分析结果,形象地表现在三维地图上,使得用户可以更加容易理解数据规律和趋势。
通俗地讲,三维地图可视化可以将地理数据更清晰直白地展现出来。
开发前准备
1. 城市建筑矢量数据 (.shp文件)2. 搭建一个vue + cesium 的开发环境
3. .shp 矢量数据转 GeoJson 或者 3dtiles ( 建议使用 3dtiles 来加载 ) 4. cesium 基础使用 ( 加载底图以及控件等 )
5. vue 基础 ( 本人做的所有实例都是基于vue来开发的 )
想要获取全国62个城市矢量数据以及shp转3dtiles转换工具,可以关注【 前端开发爱好者 】,后台回复 【 三维城市建筑可视化 】即可获取下载链接
先看看最终要实现的效果吧 ,是不是感觉很酷呢,赶快关注 【 前端开发爱好者 】获取资源,自己动手来尝试一下吧 !!!
具体环境配置以及数据转换操作和代码实现
1. 环境搭建 ( vue + cesium )
npm install cesium --save
webpack配置
// resolveresolve: { alias: { cesium: path.resolve(__dirname, '../node_modules/cesium/Source') } }, // plugins plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html' }), // Copy Cesium Assets, Widgets, and Workers to a static directory new CopyWebpackPlugin([ { from: path.join('node_modules/cesium/Source', '../Build/Cesium/Workers'), to: 'Workers' } ]), new CopyWebpackPlugin([ { from: path.join('node_modules/cesium/Source', 'Assets'), to: 'Assets' } ]), new CopyWebpackPlugin([ { from: path.join('node_modules/cesium/Source', 'Widgets'), to: 'Widgets' } ]), new webpack.DefinePlugin({ // Define relative base path in cesium for loading assets CESIUM_BASE_URL: JSON.stringify('') }) ],
组件内引入
import Cesium from 'cesium/Cesium' import 'cesium/Widgets/widgets.css'
至此,基本环境已经搭建完成, 下一步 把准备好的 shp 数据转换成 3dtiles
2. 数据转换
ceisum加载shp格式的建筑。有两种思路,目前推荐第二种。
方法一:将shp格式转换为geojson格式,然后采用cesium提供的接口加载到ceisum 中。
严重缺陷:在面对大场景问题,即数据量较大时,非常容易卡死、崩溃
方法二:将shp转换为3dtiles,然后加载到ceiusm中。
3dtiles是ceisum解决大场景问题专门提供的一种数据格式。
打开下载好的 shp 数据 和转换工具 按照图上所示,根据自己的需求来选择即可,这里除了做一些基础设置外还可以设置贴图和地形高程,在这里不做过多阐述,可自行研究
最终选择输出目录,点击确认,即可获得自己想要的 3dtiles 数据
想要获取全国62个城市矢量数据以及shp转3dtiles转换工具,可以关注【 前端开发爱好者 】,后台回复 【 三维城市建筑可视化 】即可获取下载链接
数据和开发环境都有了,那就直接上代码吧:
1. 首先到官方获取 token https://cesium.com/ion/signin/tokens
2. 组件中设置 token
Cesium.Ion.defaultAccessToken = "你自己的token"
3.初始化地图,加载高德影像地图 ( 这里可以加载多种地图,比如 mapbox Google地图 天地图 等,本实列加载的是高德 )
var viewer = new Cesium.Viewer("cesiumContainer", { terrainProvider: Cesium.createWorldTerrain({ // required for water effects requestWaterMask: true, // required for terrain lighting requestVertexNormals: true, }), animation: true, //是否显示动画控件 animation: false, //是否显示动画控件 scene3DOnly: true, baseLayerPicker: false, //是否显示图层选择控件 geocoder: true, //是否显示地名查找控件 timeline: true, //是否显示时间线控件 sceneModePicker: true, //是否显示投影方式控件 navigationHelpButton: false, //是否显示帮助信息控件 infoBox: true, //是否显示点击要素之后显示的信息 // 加载高德影像地图 imageryProvider: new Cesium.UrlTemplateImageryProvider({ url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}", }), });
4. 加载转换好的 3dtiles 数据
3dtiles 数据最好是本地启个服务去加载,最简单的方式就是 vscode live server
var palaceTileset = new Cesium.Cesium3DTileset({ url: "http://127.0.0.1:5501/tileset.json", }); viewer.scene.primitives.add(palaceTileset); palaceTileset.readyPromise .then(function (tileset) { viewer.scene.primitives.add(tileset); viewer.zoomTo( tileset, new Cesium.HeadingPitchRange( 0.5, -0.2, tileset.boundingSphere.radius * 1.0 ) ); }) .otherwise(function (error) { console.log(error); });
5. 这个时候建筑加载出来的还是白色, 为了效果可以加点色 (根据建筑物高度设置不同的颜色,也可以根据经纬度来设置,具体查看官方实列 )
https://sandcastle.cesium.com/index.html?src=3D%20Tiles%20Feature%20Styling.html
palaceTileset.style = new Cesium.Cesium3DTileStyle({ color: { conditions: [ ["${Floor} >= 300", "rgba(45, 0, 75, 0.5)"], ["${Floor} >= 200", "rgba(102, 71, 151,0.5)"], ["${Floor} >= 100", "rgba(45, 0, 75, 0.5)"], ["${Floor} >= 50", "rgba(102, 71, 151,0.5)"], ["${Floor} >= 25", "rgba(252, 230, 200,0.5)"], ["${Floor} >= 10", "rgba(248, 176, 87,0.5)"], ["${Floor} >= 5", "rgba(198, 106, 11,0.5)"], ["true", "rgb(127, 59, 8)"], ], }, });
6. 最后来给地图加个点吧
let entity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(118.78, 32.07, 20.61), point: { color: Cesium.Color.RED, //点位颜色 pixelSize: 10, //像素点大小 }, label: { // text : '测试名称', font: "14pt Source Han Sans CN", //字体样式 fillColor: Cesium.Color.BLACK, //字体颜色 backgroundColor: Cesium.Color.AQUA, //背景颜色 showBackground: true, //是否显示背景颜色 style: Cesium.LabelStyle.FILL, //label样式 outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.CENTER, //垂直位置 horizontalOrigin: Cesium.HorizontalOrigin.LEFT, //水平位置 pixelOffset: new Cesium.Cartesian2(10, 0), //偏移 }, });
本人,某个不知名小公司的前端小菜鸡,由于技术太菜,业余时间总是喜欢捣鼓一些花里胡哨的东西,一边学习一边分享,希望能够和大家一起成长,梦想着成为一位前端大大牛。