二三维切换基本思路:
- 创建两个视图器,二维视图器 MapView和三维视图器SceneView;
- 两个视图器共用一个div容易,两个视图器的container相同,每次只放入一个视图器;
- 二三维场景切换时 要使用同一个viewpoint信息,确保切换后视点相同;
具体代码如下所示:
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>二三维切换</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#infoDiv {
position: absolute;
top: 15px;
left: 60px;
}
#infoDiv input {
border: none;
box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 2px;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.23/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.23/"></script>
<script>
require(["esri/views/MapView", "esri/views/SceneView", "esri/WebMap","esri/Map", "esri/WebScene"], (
MapView,
SceneView,
WebMap,
WebScene,
Map
) => {
const switchButton = document.getElementById("switch-btn");
const appConfig = {
mapView: null,
sceneView: null,
activeView: null,
container: "viewDiv" // 存放视图器的div容器id
};
//创建二维场景地图
const map = new Map({
basemap: "streets"
});
//创建三维场景地图 添加了ground 地形数据
const scene = new WebScene({
basemap: "satellite",
ground: "world-topobathymetry"
});
//初始化地图层级和中心点 中心点在西安附近 div容器 就是 <div id="viewDiv"></div>
const initialViewParams = {
zoom: 3,
center: [109, 39],
container: appConfig.container
};
// 创建二维视图器,并设置为当前视图器
appConfig.mapView = createView(initialViewParams, "2d");
appConfig.mapView.map = map;
appConfig.activeView = appConfig.mapView;
// 创建三维视图器 但是不要初始化视图器的容器
initialViewParams.container = null;
initialViewParams.map = scene;
appConfig.sceneView = createView(initialViewParams, "3d");
// switch the view between 2D and 3D each time the button is clicked
switchButton.addEventListener("click", () => {
switchView();
});
// 切换二三维视图方法
function switchView() {
const is3D = appConfig.activeView.type === "3d";
//首先克隆当前视图器的视点信息
const activeViewpoint = appConfig.activeView.viewpoint.clone();
// 把当前视图器的容易移除
appConfig.activeView.container = null;
if (is3D) {
// if the input view is a SceneView, set the viewpoint on the
// mapView instance. Set the container on the mapView and flag
// it as the active view
appConfig.mapView.viewpoint = activeViewpoint;
appConfig.mapView.container = appConfig.container;
appConfig.activeView = appConfig.mapView;
switchButton.value = "3D";
} else {
appConfig.sceneView.viewpoint = activeViewpoint;
appConfig.sceneView.container = appConfig.container;
appConfig.activeView = appConfig.sceneView;
switchButton.value = "2D";
}
}
// 根据参数创建视图器
function createView(params, type) {
let view;
if (type === "2d") {
view = new MapView(params);
return view;
} else {
view = new SceneView(params);
}
return view;
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="infoDiv">
<input
type="button"
id="switch-btn"
value="3D"
/>
</div>
</body>
</html>
效果如下:
需要注意
- 每个视图器都有一个自己的map 因为有些图层在二维场景中无法显示,例如地形;
- 视图切换时,首要工作是把当前的viewpoint 信息克隆出来,然在再把当前视图器的容器移除,顺序不能变。