Mars3D入门示例
1. 引言
Mars3D是基于Cesium的Web端的三维GIS库,对Cesium做了进一步封装和扩展
Mars3D官网:Mars3D三维可视化平台 | 火星科技
Mars3D开发手册:开发教程 - Mars3D三维可视化平台 | 火星科技
GitHub地址:Mars3D三维可视化平台 | 火星科技
API文档:API文档 - Mars3D三维可视化平台 | 火星科技
2. 示例
以下是一些基于原生JavaScript的使用案例
2.1 创建三维场景
2.1.1 快速创建地球
即new一个Map,可选的设置参数有:
- 场景scene
- 控件control
- 特效effect
- ......
具体可参考:API文档 - Mars3D三维可视化平台 | 火星科技
这里仅设置部分底图参数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!--引入cesium基础lib-->
<link
href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js"
type="text/javascript"
></script>
<!--引入mars3d库lib-->
<link
href="https://unpkg.com/mars3d/dist/mars3d.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d/dist/mars3d.js"
type="text/javascript"
></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script type="text/javascript">
let mapOptions = {
basemaps: [{ name: "高德", type: "gaode", layer: "img_d", show: true }],
};
let map = new mars3d.Map("mars3dContainer", mapOptions);
</script>
</body>
</html>
2.1.2 根据配置创建
通过配置文件创建地图,配置项与上述的快速创建的配置项相同
config.json
文件(和上面的配置一样):
[
{
"name": "高德",
"type": "gaode",
"layer": "img_d",
"show": true
}
]
加载代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!--引入cesium基础lib-->
<link
href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js"
type="text/javascript"
></script>
<!--引入mars3d库lib-->
<link
href="https://unpkg.com/mars3d/dist/mars3d.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d/dist/mars3d.js"
type="text/javascript"
></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script type="text/javascript">
fetch("./config/config.json")
.then((res) => res.json())
.then((config) => {
let mapOptions = config.mars3d
let map = new mars3d.Map("mars3dContainer", mapOptions)
});
</script>
</body>
</html>
2.1.3 根据Cesium创建
先使用Cesium创建一个地球(Viewer),再构造为Mars3d的Map对象:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!--引入cesium基础lib-->
<link
href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js"
type="text/javascript"
></script>
<!--引入mars3d库lib-->
<link
href="https://unpkg.com/mars3d/dist/mars3d.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d/dist/mars3d.js"
type="text/javascript"
></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script type="text/javascript">
const viewer = new Cesium.Viewer("mars3dContainer");
let mapOptions = {
scene: {
center: {
lat: 30.054604,
lng: 108.885436,
alt: 17036414,
heading: 0,
pitch: -90,
},
fxaa: true,
},
};
const map = new mars3d.Map(viewer, mapOptions);
</script>
</body>
</html>
2.2 UI控件样板
在主页面设置UI控件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!--引入cesium基础lib-->
<link
href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js"
type="text/javascript"
></script>
<!--引入mars3d库lib-->
<link
href="https://unpkg.com/mars3d/dist/mars3d.css"
rel="stylesheet"
type="text/css"
/>
<script
src="https://unpkg.com/mars3d/dist/mars3d.js"
type="text/javascript"
></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
.infoview {
position: absolute;
top: 10px;
right: 10px;
padding: 10px 15px;
border-radius: 4px;
border: 1px solid rgba(128, 128, 128, 0.5);
color: #ffffff;
background: rgba(0, 0, 0, 0.4);
box-shadow: 0 3px 14px rgb(128 128 128 / 50%);
z-index: 19870101;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<div class="infoview" style="overflow: auto; max-height: 850px">
<table class="mars-table">
<tbody>
<tr>
<td>简单文本:</td>
<td>
<input
id="txtUrl"
type="text"
value=""
required
class="form-control"
placeholder="请输入"
/>
</td>
</tr>
<tr>
<td>下拉框:</td>
<td>
<select id="txtCrs" class="selectpicker form-control">
<option value="" selected="selected">默认</option>
<option value="EPSG:3857">火星</option>
<option value="EPSG:4326">地球</option>
<option value="EPSG:4490">太阳</option>
</select>
</td>
</tr>
<tr>
<td class="nametd">日期:</td>
<td>
<input
type="text"
class="form-control"
id="txtStartTime"
placeholder="YYYY-MM-DD"
/>
</td>
</tr>
<tr>
<td>滑动条:</td>
<td class="slider">
<input
id="slider_brightness"
type="text"
data-slider-min="-0.5"
data-slider-max="1.5"
data-slider-step="0.01"
data-slider-value="-0.5"
/>
</td>
</tr>
<tr>
<td>刻度滑动条:</td>
<td class="slider">
<input id="slider_showLevel" type="text" />
</td>
</tr>
</tbody>
</table>
</div>
<script type="text/javascript">
let mapOptions = {
basemaps: [{ name: "高德", type: "gaode", layer: "img_d", show: true }],
};
const map = new mars3d.Map("mars3dContainer", mapOptions);
</script>
</body>
</html>
2.3 设置地图参数
2.3.1 设置场景参数
在地图创建时可以直接设置一些参数,比如场景、底图等,在地图创建好以后,也可以直接设置这些参数,使用类似于map.setSceneOptions(options)
等API
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{ name: "高德", type: "gaode", layer: "img_d", show: true }],
};
const map = new mars3d.Map("mars3dContainer", mapOptions);
map.setSceneOptions({
center: { lat: 26.8764, lng: 91.148781, alt: 223798, heading: 0, pitch: -45 }
})
</script>
</body>
</html>
2.3.2 设置三维地形
三维地形可以在Map创建时设置terrain
参数来加,也可以在地图创建后加载
在创建地球后更新terrainProvider(用 mars3d.layer.createTerrainProvider工厂方法创建)[目前1个球只支持1个地形服务]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{ name: "高德", type: "gaode", layer: "img_d", show: true }],
};
const map = new mars3d.Map("mars3dContainer", mapOptions);
map.setSceneOptions({
center: { lat: 26.8764, lng: 91.148781, alt: 223798, heading: 0, pitch: -45 }
})
map.terrainProvider = mars3d.LayerUtil.createTerrainProvider({
url: "http://data.mars3d.cn/terrain"
})
</script>
</body>
</html>
2.3.3 设置底图
底图(basemap)可以在加载时设置,也可以在底图创建好后加载
加载底图时建议开启底图切换控件(baseLayerPicker),从而实现底图切换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}, {
name: "XYZ地图",
icon: "./icon/mapboxSatellite.png",
type: "xyz",
url: "//data.mars3d.cn/tile/googleImg/{z}/{x}/{y}.jpg",
maximumLevel: 12
}],
control: {
baseLayerPicker: true, // basemaps底图切换按钮
homeButton: true, // 视角复位按钮
sceneModePicker: true, // 二三维切换按钮
navigationHelpButton: true, // 帮助按钮
fullscreenButton: true, // 全屏按钮
contextmenu: { hasDefault: true } // 右键菜单
}
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.setSceneOptions({
center: { lat: 26.8764, lng: 91.148781, alt: 223798, heading: 0, pitch: -45 }
})
map.terrainProvider = mars3d.LayerUtil.createTerrainProvider({
url: "http://data.mars3d.cn/terrain"
})
</script>
</body>
</html>
2.3.4 添加图层
图层(layer)可以在创建时配置,也可以在底图创建后添加(addLayer)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}],
control: {
baseLayerPicker: true, // basemaps底图切换按钮
homeButton: true, // 视角复位按钮
sceneModePicker: true, // 二三维切换按钮
navigationHelpButton: true, // 帮助按钮
fullscreenButton: true, // 全屏按钮
contextmenu: { hasDefault: true } // 右键菜单
},
layers: [{
name: "天地图注记",
type: "tdt",
layer: "img_z",
show: true
}]
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.setSceneOptions({
center: { lat: 31.72076, lng: 120.233888, alt: 223798, heading: 0, pitch: -45 }
})
map.terrainProvider = mars3d.LayerUtil.createTerrainProvider({
url: "http://data.mars3d.cn/terrain"
})
const layerImg = mars3d.LayerUtil.create({
type: "image",
url: "//data.mars3d.cn//file/img/radar/201906211112.PNG",
rectangle: { xmin: 73.16895, xmax: 134.86816, ymin: 12.2023, ymax: 54.11485 },
alpha: 0.7
})
map.addLayer(layerImg)
</script>
</body>
</html>
2.3.5 地图控件
地图控件可以在地图创建时配置,也可以在地图创建后添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}],
control: {
baseLayerPicker: true, // basemaps底图切换按钮
homeButton: true, // 视角复位按钮
sceneModePicker: true, // 二三维切换按钮
navigationHelpButton: true, // 帮助按钮
fullscreenButton: true, // 全屏按钮
contextmenu: { hasDefault: true } // 右键菜单
},
layers: [{
name: "天地图注记",
type: "tdt",
layer: "img_z",
show: true
}]
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.setSceneOptions({
center: { lat: 31.72076, lng: 120.233888, alt: 223798, heading: 0, pitch: -45 }
})
const locationBar = new mars3d.control.LocationBar()
map.addControl(locationBar)
</script>
</body>
</html>
2.4 地图事件
使用map.on(event, callback)
函数监听地图事件,地图事件主要有单击、双击等,具体事件可以参考:API文档 - Mars3D三维可视化平台 | 火星科技
使用map.on(event, callback)
函数监听地图事件,使用map.off(event, callback)
函数解除监听
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}],
control: {
baseLayerPicker: true,
homeButton: true,
sceneModePicker: true,
navigationHelpButton: true,
fullscreenButton: true,
contextmenu: { hasDefault: true }
},
layers: [{
name: "天地图注记",
type: "tdt",
layer: "img_z",
show: true
}]
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.on("click", function (e){
console.log(e)
})
</script>
</body>
</html>
2.5 地形分析
使用Mars3D提供的地形分析函数实现地形分析
2.5.1 地形开挖
- new mars3d.thing.TerrainClip(options)
地形开挖, 基于地球材质,可以多个区域开挖,具体参考:API文档 - Mars3D三维可视化平台 | 火星科技
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}],
control: {
baseLayerPicker: true,
homeButton: true,
sceneModePicker: true,
navigationHelpButton: true,
fullscreenButton: true,
contextmenu: { hasDefault: true }
},
layers: [{
name: "天地图注记",
type: "tdt",
layer: "img_z",
show: true
}]
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.on("click", function (e) {
console.log(e)
})
map.setSceneOptions({
center: { lat: 30.899171, lng: 116.334222, alt: 23798, heading: 0, pitch: -45 }
})
map.terrainProvider = mars3d.LayerUtil.createTerrainProvider({
url: "http://data.mars3d.cn/terrain"
})
const terrainClip = new mars3d.thing.TerrainClip({
positions: [
[116.334222, 30.899171, 645.46],
[116.370874, 30.899171, 645.46],
[116.370874, 30.944509, 645.46],
[116.334222, 30.944509, 645.46]
],
diffHeight: 50, // 井的深度
image: "http://mars3d.cn/img/textures/poly-stone.jpg",
imageBottom: "http://mars3d.cn/img/textures/poly-soil.jpg",
splitNum: 80 // 井边界插值数
})
map.addThing(terrainClip)
</script>
</body>
</html>
2.5.2 等高线生成
- new mars3d.thing.ContourLine(options)
等高线生成,具体参数可以参考:API文档 - Mars3D三维可视化平台 | 火星科技
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}],
control: {
baseLayerPicker: true,
homeButton: true,
sceneModePicker: true,
navigationHelpButton: true,
fullscreenButton: true,
contextmenu: { hasDefault: true }
},
layers: [{
name: "天地图注记",
type: "tdt",
layer: "img_z",
show: true
}]
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.on("click", function (e) {
console.log(e)
})
map.setSceneOptions({
center: { lat: 30.899171, lng: 116.334222, alt: 23798, heading: 0, pitch: -45 }
})
map.terrainProvider = mars3d.LayerUtil.createTerrainProvider({
url: "http://data.mars3d.cn/terrain"
})
const contourLine = new mars3d.thing.ContourLine({
positions: [
[116.334222, 30.899171, 645.46],
[116.370874, 30.899171, 645.46],
[116.370874, 30.944509, 645.46],
[116.334222, 30.944509, 645.46]
]
})
map.addThing(contourLine)
</script>
</body>
</html>
2.5.3 坡度坡向
- new mars3d.thing.Slope(options)
坡度坡向分析,具体参数参考:API文档 - Mars3D三维可视化平台 | 火星科技
const slope = new mars3d.thing.Slope({
positions: [
[116.334222, 30.899171, 645.46],
[116.370874, 30.899171, 645.46],
[116.370874, 30.944509, 645.46],
[116.334222, 30.944509, 645.46]
]
})
map.addThing(slope)
2.5.4 淹没分析
- new mars3d.thing.FloodByMaterial(options)
淹没分析 , 基于地球材质,可以多个区域,具体可以参考:API文档 - Mars3D三维可视化平台 | 火星科技
const floodByMaterial = new mars3d.thing.FloodByMaterial({
positions: [
new Cesium.Cartesian3(-2410198.2775535597, 4925725.562201189, 3248372.021893719),
new Cesium.Cartesian3(-2426218.5805536904, 4917854.35435215, 3248372.021893719),
new Cesium.Cartesian3(-2421804.8608153155, 4908907.909457106, 3265042.349716699),
new Cesium.Cartesian3(-2405813.7015733495, 4916764.7981900815, 3265042.349716699)
],
speed: 500,
minHeight: 0,
maxHeight: 2000,
color: "rgba(0, 123, 230, 0.5)"
})
floodByMaterial.on(mars3d.EventType.end, function (event) {
console.log('分析完成', event)
})
map.addThing(floodByMaterial)
floodByMaterial.restart()
2.6 矢量图层
2.6.1 graphic 数据图层
GraphicLayer是Mars3D中的矢量图层,创建矢量数据的主要步骤如下:
- 创建矢量图层并添加到Map中
- 创建矢量数据对象
- 将矢量数据对象添加到矢量图层中
一个简单的添加点数据代码如下:
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
const graphicPoint = new mars3d.graphic.PointEntity({
position: [116.244399, 30.920459, 573.6],
style: {
color: "#ff0000",
pixelSize: 10,
outlineColor: "#ffffff",
outlineWidth: 2,
label: {
text: "我是点",
font_size: 18,
color: "#ffffff",
pixelOffsetY: -10,
distanceDisplayCondition: true,
distanceDisplayCondition_far: 500000,
distanceDisplayCondition_near: 0
}
}
})
graphicLayer.addGraphic(graphicPoint)
2.6.2 DIV矢量对象
DIV矢量对象是Mars3D中一种多用于展示与标注点对象
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
const graphicDiv = new mars3d.graphic.DivGraphic({
position: [116.244399, 30.920459, 573.6],
style: {
html: `<div style='border:1px solid #f00'>
<p style='color: #0ff'>我是DIV矢量对象</p>
</div>`
}
})
graphicLayer.addGraphic(graphicDiv)
2.6.3 glTF模型
glTF是一种针对GL的三维数据格式,成为了 Web 上的3D 对象标准(Web导出的通用标准)
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
const gltf = new mars3d.graphic.ModelEntity({
position: [121.507762, 31.233975, 200],
style: {
url: "//data.mars3d.cn/gltf/mars/shanghai/scene.gltf",
scale: 520,
heading: 215
}
})
graphicLayer.addGraphic(gltf)
2.6.4 3D Tiles模型
3D Tiles 是在glTF的基础上,加入了分层LOD的概念(可以把3D Tiles简单地理解为带有 LOD 的 glTF ),专门为流式传输和渲染海量 3D 地理空间数据而设计的,例如倾斜摄影、3D 建筑、BIM/CAD、实例化要素集和点云
tiles3dLayer = new mars3d.layer.TilesetLayer({
name: "县城社区",
url: "//data.mars3d.cn/3dtiles/qx-shequ/tileset.json",
position: { alt: 11.5 },
maximumScreenSpaceError: 1,
maximumMemoryUsage: 1024,
dynamicScreenSpaceError: true,
cullWithChildrenBounds: false,
skipLevelOfDetail: true,
preferLeaves: true,
center: { lat: 28.439577, lng: 119.476925, alt: 229, heading: 57, pitch: -29 },
flyTo: true
})
map.addLayer(tiles3dLayer)
2.6.5 GeoJSON
GeoJSON是常用的矢量数据格式
const geoJsonLayer = new mars3d.layer.GeoJsonLayer({
url: "//data.mars3d.cn/file/geojson/wuhan-line2.json",
symbol: {
type: "polylineC",
styleOptions: {
width: 10, // 线宽
materialType: "PolylineGlow",
materialOptions: {
color: "#FF4500",
opacity: 0.9,
glowPower: 0.1 // 发光强度
}
}
},
show: true
})
map.addLayer(geoJsonLayer)
2.6.6 WFS服务
WFS是OGC定义的矢量数据服务
const wfsLayer = new mars3d.layer.WfsLayer({
name: "建筑物面WFS",
url: "//server.mars3d.cn/geoserver/mars/wfs",
layer: "mars:hfjzw",
parameters: {
// 支持所有wfs的参数
maxFeatures: 210
},
minimumLevel: 1,
symbol: {
type: "polygonP",
styleOptions: {
color: "#00469c",
outline: false,
opacity: 1
}
},
buildings: {
cloumn: "floor"
},
debuggerTileInfo: false,
popup: "名称:{NAME}<br />层数:{floor}",
show: true
})
map.addLayer(wfsLayer)
2.6.7 WFS查询
WFS允许对矢量要素的增删改查
const queryMapserver = new mars3d.query.QueryGeoServer({
url: "//server.mars3d.cn/geoserver/mars/wfs",
layer: "mars:hfjy"
})
map.graphicLayer.startDraw({
type: "rectangle",
style: {
color: "#00FF00",
opacity: 0.3,
outline: true,
outlineColor: "#ffffff",
clampToGround: true
},
success: function (graphic) {
drawGraphic = graphic
console.log("矩形:", drawGraphic.toGeoJSON({ outline: true }))
queryMapserver.query({
graphic: drawGraphic,
success: (result) => {
console.log(result)
},
error: (e) => {
console.log(e)
}
})
}
})
2.7 矢量数据
2.7.1 Entity基础对象
Entity实体是Mars3D中的矢量对象,主要有以下Entity:
- BillboardEntity
- BoxEntity
- CanvasLabelEntity
- CircleEntity
- CorridorEntity
- CurveEntity
- CylinderEntity
- DivBillboardEntity
- EllipseEntity
- EllipsoidEntity
- FlickerEntity
- FontBillboardEntity
- LabelEntity
- ModelEntity
- PathEntity
- PlaneEntity
- PointEntity
- PolygonEntity
- PolylineEntity
- PolylineVolumeEntity
- RectangleEntity
- WallEntity
创建Entity对象的主要步骤如上述所说:
- 创建矢量图层并添加到Map中
- 创建矢量数据对象
- 将矢量数据对象添加到矢量图层中
以下是示例创建并展示一个PolylineEntity和PolygonEntity:
// 创建矢量数据图层
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
map.setSceneOptions({
center: { lat: 31.52076, lng: 117.233888, alt: 23798, heading: 0, pitch: -45 }
})
const polylineEntity = new mars3d.graphic.PolylineEntity({
positions: [
[117.220337, 31.832987, 42.8],
[117.220242, 31.835234, 45.6],
[117.216263, 31.835251, 39.3],
[117.217219, 31.819929, 35.8],
[117.223096, 31.818342, 29.8],
[117.249686, 31.818964, 40.1],
[117.263171, 31.816664, 35.2],
[117.278695, 31.816107, 35.5],
[117.279826, 31.804185, 34.5],
[117.286308, 31.804112, 29.2],
[117.28621, 31.801059, 24.6]
],
style: {
width: 5,
color: "#3388ff",
label: { text: "鼠标移入会高亮", pixelOffsetY: -30 },
// 高亮时的样式(默认为鼠标移入,也可以指定type:'click'单击高亮),构造后也可以openHighlight、closeHighlight方法来手动调用
highlight: {
color: "#ff0000"
}
},
})
graphicLayer.addGraphic(polylineEntity)
const polygonEntity = new mars3d.graphic.PolygonEntity({
positions: [
[117.220337, 31.832987, 42.8],
[117.220242, 31.835234, 45.6],
[117.216263, 31.835251, 39.3],
[117.217219, 31.819929, 35.8],
[117.220337, 31.832987, 42.8]
],
style: {
width: 5,
color: "#0ff",
highlight: {
color: "#ff0000"
}
},
})
graphicLayer.addGraphic(polygonEntity)
2.7.2 Primitive基础对象
Primitive API 的主要目的是为了完成(可视化)任务的最少的抽象需求,Primitive方式更接近渲染引擎底层,拥有更好的绘制性能,但是它的封装不如Entity API,Entity使用起来更方便
Primitive图元也是Mars3D中的矢量对象,主要有以下Primitive:
- BillboardPrimitive
- BoxPrimitive
- CirclePrimitive
- CloudPrimitive
- ConeTrackPrimitive
- CorridorPrimitive
- CylinderPrimitive
- EllipsoidPrimitive
- FrustumPrimitive
- LabelPrimitive
- ModelPrimitive
- PlanePrimitive
- PointPrimitive
- PolygonPrimitive
- PolylinePrimitive
- PolylineSimplePrimitive
- PolylineVolumePrimitive
- RectanglePrimitive
- WallPrimitive
以下是示例创建并展示一个PolylinePrimitive和PolygonPrimitive(和Entity基本类似):
// 创建矢量数据图层
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
map.setSceneOptions({
center: { lat: 31.52076, lng: 117.233888, alt: 23798, heading: 0, pitch: -45 }
})
const polylinePrimitive = new mars3d.graphic.PolylinePrimitive({
positions: [
[117.220337, 31.832987, 42.8],
[117.220242, 31.835234, 45.6],
[117.216263, 31.835251, 39.3],
[117.217219, 31.819929, 35.8],
[117.223096, 31.818342, 29.8],
[117.249686, 31.818964, 40.1],
[117.263171, 31.816664, 35.2],
[117.278695, 31.816107, 35.5],
[117.279826, 31.804185, 34.5],
[117.286308, 31.804112, 29.2],
[117.28621, 31.801059, 24.6]
],
style: {
width: 5,
color: "#3388ff",
label: { text: "鼠标移入会高亮", pixelOffsetY: -30 },
// 高亮时的样式(默认为鼠标移入,也可以指定type:'click'单击高亮),构造后也可以openHighlight、closeHighlight方法来手动调用
highlight: {
color: "#ff0000"
}
},
})
graphicLayer.addGraphic(polylinePrimitive)
const polygonPrimitive = new mars3d.graphic.PolygonPrimitive({
positions: [
[117.220337, 31.832987, 42.8],
[117.220242, 31.835234, 45.6],
[117.216263, 31.835251, 39.3],
[117.217219, 31.819929, 35.8],
[117.223096, 31.818342, 29.8]
],
style: {
width: 5,
color: "#0ff",
highlight: {
color: "#ff0000"
}
},
})
graphicLayer.addGraphic(polygonPrimitive)
2.7.3 CombinePrimitive对象
CombinePrimitive对象是合并渲染的Primitive图元 ,更适合大数据渲染,主要的有:
- BoxCombine
- CircleCombine
- CorridorCombine
- CylinderCombine
- EllipsoidCombine
- FrustumCombine
- ModelCombine
- PlaneCombine
- PolygonCombine
- PolylineCombine
- PolylineVolumeCombine
- RectangleCombine
- WallCombine
- WaterCombine
以下是示例创建并展示一个PolylinePrimitive和PolygonPrimitive:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--引入cesium基础lib-->
<link href="https://unpkg.com/mars3d-cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d-cesium/Build/Cesium/Cesium.js" type="text/javascript"></script>
<!--引入turf基础lib-->
<script src="http://mars3d.cn/lib/turf/turf.min.js"></script>
<!--引入mars3d库lib-->
<link href="https://unpkg.com/mars3d/dist/mars3d.css" rel="stylesheet" type="text/css" />
<script src="https://unpkg.com/mars3d/dist/mars3d.js" type="text/javascript"></script>
<style>
html,
body,
.mars3d-container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="mars3dContainer" class="mars3d-container"></div>
<script>
let mapOptions = {
basemaps: [{
name: "高德",
icon: "./icon/offline.png",
type: "gaode",
layer: "img_d",
show: true
}],
control: {
baseLayerPicker: true, // basemaps底图切换按钮
homeButton: true, // 视角复位按钮
sceneModePicker: true, // 二三维切换按钮
navigationHelpButton: true, // 帮助按钮
fullscreenButton: true, // 全屏按钮
contextmenu: { hasDefault: true } // 右键菜单
},
layers: [{
name: "天地图注记",
type: "tdt",
layer: "img_z",
show: true
}]
}
const map = new mars3d.Map("mars3dContainer", mapOptions)
map.setSceneOptions({
center: { lat: 31.72076, lng: 117.033888, alt: 223798, heading: 0, pitch: -45 }
})
// 创建矢量数据图层
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
map.setSceneOptions({
center: { lat: 31.82076, lng: 117.233888, alt: 23798, heading: 0, pitch: -45 }
})
// 生成演示数据(测试数据量)
let bbox = [116.984788, 31.625909, 117.484068, 32.021504]
let count = 1000
let result = mars3d.PolyUtil.getGridPoints(bbox, count, 30)
console.log("生成的测试网格坐标", result)
let arrData = []
for (let j = 0; j < result.points.length; ++j) {
let position = result.points[j]
let index = j + 1
let pt1 = mars3d.PointUtil.getPositionByDirectionAndLen(position, 225, result.radius)
let pt2 = mars3d.PointUtil.getPositionByDirectionAndLen(position, 315, result.radius)
arrData.push({
positions: [pt1, position, pt2],
style: {
width: 3.0,
color: Cesium.Color.fromRandom({ alpha: 1.0 })
},
attr: { index: index }
})
}
// 多个线对象的合并渲染。
const polylineCombine = new mars3d.graphic.PolylineCombine({
instances: arrData,
// 高亮时的样式
highlight: {
type: mars3d.EventType.click,
color: Cesium.Color.YELLOW
}
})
graphicLayer.addGraphic(polylineCombine)
// 多个面对象的合并渲染
const polygonCombine = new mars3d.graphic.PolygonCombine({
instances: arrData,
})
graphicLayer.addGraphic(polygonCombine)
</script>
</body>
</html>
2.7.4 ParticleSystem粒子对象
ParticleSystem粒子对象是一些粒子效果
// 创建矢量数据图层
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
map.setSceneOptions({
center: { lat: 31.815135, lng: 117.233888, alt: 898, heading: 0, pitch: -45 }
})
const particleSystem = new mars3d.graphic.ParticleSystem({
position: Cesium.Cartesian3.fromDegrees(117.224855, 31.815135, 28.05), // 位置
style: {
image: "./img/particle/penquan.png",
particleSize: 8, // 粒子大小(单位:像素)
emissionRate: 100.0, // 发射速率 (单位:次/秒)
heading: 290, // 方向角
pitch: 40, // 俯仰角
gravity: -3.5, // 重力因子,会修改速度矢量以改变方向或速度(基于物理的效果)
transZ: 5, // 离地高度(单位:米)
maxHeight: 5000, // 超出该高度后不显示粒子效果
startColor: new Cesium.Color(1, 1, 1, 0.6), // 开始颜色
endColor: new Cesium.Color(0.8, 0.86, 1, 0.4), // 结束颜色
startScale: 1.0, // 开始比例(单位:相对于imageSize大小的倍数)
endScale: 4.0, // 结束比例(单位:相对于imageSize大小的倍数)
minimumParticleLife: 6, // 最小寿命时间(秒)
maximumParticleLife: 7, // 最大寿命时间(秒)
minimumSpeed: 9.0, // 最小速度(米/秒)
maximumSpeed: 9.5 // 最大速度(米/秒)
},
attr: { remark: "水柱粒子效果" }
})
graphicLayer.addGraphic(particleSystem)
2.7.5 漫游路线对象
漫游路线对象展示对象按照一定轨迹移动,主要有以下漫游路线对象:
以下是固定路线(FixedRoute)游:
const fixedRoute = new mars3d.graphic.FixedRoute({
speed: 100,
positions: [
[117.298794, 31.882442, 500],
[117.249731, 31.88091, 600]
],
model: {
url: "//data.mars3d.cn/gltf/mars/zhanji.glb",
scale: 0.01,
minimumPixelSize: 60
},
path: {
color: "#ffff00",
opacity: 0.5,
width: 1,
leadTime: 0
},
coneTrack: {
angle: 5, // 半场角度
color: "rgba(255,0,0,0.5)"
}
})
graphicLayer.addGraphic(fixedRoute)
2.7.6 视频融合对象
投射视频物体表面
// 创建矢量数据图层
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
map.setSceneOptions({
center: { lat: 31.815135, lng: 117.233888, alt: 2898, heading: 0, pitch: -45 }
})
const video3D = new mars3d.graphic.Video3D({
position: [117.233888, 31.815135, 0],
style: {
url: "//data.mars3d.cn/file/video/menqian.mp4",
maskImage: "img/textures/video-mask.png", // 羽化视频四周,融合更美观
angle: 46.3,
angle2: 15.5,
heading: 178.5,
pitch: -49.5,
showFrustum: true
}
})
graphicLayer.addGraphic(video3D)
2.8 样式及效果
2.8.1 设置样式
样式主要就是设置style
// 模型
const tiles3dLayer = new mars3d.layer.TilesetLayer({
name: "合肥市建筑物",
url: "//data.mars3d.cn/3dtiles/jzw-hefei2/tileset.json",
maximumScreenSpaceError: 1,
maximumMemoryUsage: 1024,
style: {
color: {
conditions: [
["${height} >= 300", "rgba(45, 0, 75, 0.5)"],
["${height} >= 200", "rgb(102, 71, 151)"],
["${height} >= 100", "rgb(170, 162, 204)"],
["${height} >= 50", "rgb(224, 226, 238)"],
["${height} >= 30", "rgb(252, 230, 200)"],
["${height} >= 20", "rgb(248, 176, 87)"],
["${height} >= 10", "rgb(198, 106, 11)"],
["true", "rgb(127, 59, 8)"]
]
}
},
highlight: { type: "click", color: "#FFFF00" },
popup: [
{ field: "objectid", name: "编号" },
{ field: "name", name: "名称" },
{ field: "height", name: "楼高", unit: "米" }
]
})
map.addLayer(tiles3dLayer)
2.8.2 自定义Shader
Tileset支持自定义shader
// 创建矢量数据图层
const graphicLayer = new mars3d.layer.GraphicLayer()
map.addLayer(graphicLayer)
map.setSceneOptions({
center: { lat: 31.267519, lng: 121.42728, alt: 2923, heading: 118, pitch: -27 }
})
const tiles3dLayer = new mars3d.layer.TilesetLayer({
name: "上海市建筑物",
url: "//data.mars3d.cn/3dtiles/jzw-shanghai/tileset.json",
maximumScreenSpaceError: 8,
maximumMemoryUsage: 1024,
popup: "all"
})
// 当前效果是:根据视角距离,模型呈现不同颜色
tiles3dLayer.customShader = new Cesium.CustomShader({
lightingModel: Cesium.LightingModel.UNLIT,
fragmentShaderText: `
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)
{
material.diffuse = vec3(0.0, 0.0, 1.0);
material.diffuse.g = -fsInput.attributes.positionEC.z / 1.0e4;
} `
})
map.addLayer(tiles3dLayer)
3. 参考资料
[1]功能示例(Vue版) - Mars3D三维可视化平台 | 火星科技
[2]API文档 - Mars3D三维可视化平台 | 火星科技