需要用到:Vue 2.5 、Bootstrap 4 、ArcGIS API for JS 4.10
说明:这里的底图切换和2D/3D的切换思路和官网一致,但是实现方法完全不同,是利用Vue将初始化的参数变成响应式从而实现的无缝切换
效果:
初始状态:
初始状态是 Google 的底图,为 3D 状态
随机变换视图位置后切换底图:
不会改变视图位置
切换显示维度:
同样不会改变视图位置
关键代码:
var app = new Vue({
el:"#app",
data:{
activeLayer:null,
mapConfig:{
map:null,
dimension:"3D", // 地图的维度
container:"map-container", // 地图容器
scale:110329633.40563367, // 3D视图下的比例尺
zoom:2, // 2D视图下的比例尺
center:[105.578034,34.062071],
},
tileLayer:{
google:{
url:"http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{level}!2i{col}!3i{row}!2m3!1e0!2sm!3i345013117!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0",
name:"谷歌地图",
img:"/map-invest/Public/image/google-map.jpg"
},
tianditu:{
url:"http://t2.tianditu.com/DataServer?T=vec_w&x={col}&y={row}&l={level}",
name:"天地图",
img:"/map-invest/Public/image/tianditu.jpg"
},
gaode:{
url:"http://webst01.is.autonavi.com/appmaptile?style=6&x={col}&y={row}&z={level}",
name:"高德地图",
img:"/map-invest/Public/image/gaode-map.jpg"
},
ersi:{
name:"Esri",
img:"/map-invest/Public/image/esri-map.jpg"
}
}
},
methods:{
// 比例尺与放大级别转换
zoomScaleExchange:function(value){
var exchangeInfo=[
591657550.500000,
295828775.300000,
147914387.600000,
73957193.820000,
36978596.910000,
18489298.450000,
9244649.227000,
4622324.614000,
2311162.307000,
1155581.153000,
577790.576700,
288895.288400,
144447.644200,
72223.822090,
36111.911040,
18055.955520,
9027.977761,
4513.988880,
2256.994440,
1128.497220,
];
if (value<21) {
return exchangeInfo[value-1];
}else{
if (value>exchangeInfo[0]) {
return 1;
}else if (value<1128.497220) {
return 20;
}else{
for(var index=0;index<exchangeInfo.length;index++){
if (exchangeInfo[index]<value) {
return index-1;
}
}
}
}
},
// 2D / 3D 切换按钮文字
relativeDimension:function(){
if (this.mapConfig.dimension==="3D") {
return "2D";
}else{
return "3D";
}
},
// 2D / 3D 切换
toggleDimension:function(){
if (this.mapConfig.dimension==="3D") {
this.mapConfig.dimension="2D";
this.set2dMap(this.activeLayer);
}else{
this.mapConfig.dimension="3D";
this.set3dMap(this.activeLayer);
}
},
// 创建3D地图
set3dMap:function(layer){
this.activeLayer=layer;
var _this=this;
require([
"esri/layers/WebTileLayer",
"esri/Map",
"esri/views/SceneView",
"esri/core/watchUtils",
],function(
WebTileLayer,
Map,
SceneView,
watchUtils,
dom
) {
if (layer.name!="Esri") {
_this.mapConfig.map = new Map();
var tiledLayer = new WebTileLayer({
urlTemplate: layer.url,
});
_this.mapConfig.map.add(tiledLayer);
}else{
_this.mapConfig.map=new Map({
basemap:"satellite"
})
}
var map_3d = new SceneView(_this.mapConfig);
watchUtils.whenTrue(map_3d,"stationary",function(){
_this.mapConfig.center=[map_3d.center.longitude,map_3d.center.latitude];
if (map_3d.viewpoint) {
_this.mapConfig.scale=map_3d.viewpoint.scale;
_this.mapConfig.zoom=_this.zoomScaleExchange(_this.mapConfig.scale);
}
console.log(map_3d);
});
}
);
},
// 创建2D地图
set2dMap:function(layer){
this.activeLayer=layer;
var _this=this;
require([
"esri/layers/WebTileLayer",
"esri/Map",
"esri/views/MapView",
"esri/core/watchUtils",
], function(
WebTileLayer,
Map,
MapView,
watchUtils,
dom,
){
if (layer.name!="Esri") {
_this.mapConfig.map = new Map();
var tiledLayer = new WebTileLayer({
urlTemplate: layer.url,
});
_this.mapConfig.map.add(tiledLayer);
}else{
_this.mapConfig.map = new Map({
basemap:"satellite",
});
}
var map_2d = new MapView(_this.mapConfig);
watchUtils.whenTrue(map_2d,"stationary",function(){
_this.mapConfig.center=[map_2d.center.longitude,map_2d.center.latitude];
if (map_2d.viewpoint) {
_this.mapConfig.scale=map_2d.viewpoint.scale;
_this.mapConfig.zoom=_this.zoomScaleExchange(_this.mapConfig.scale);
}
});
});
},
// 切换底图
selectTileLayer:function(type){
if (this.mapConfig.dimension==="3D") {
this.set3dMap(type);
}else if (this.mapConfig.dimension==="2D") {
this.set2dMap(type);
}
},
},
// 初始化
mounted:function(){
this.mapConfig.zoom=this.zoomScaleExchange(this.mapConfig.scale);
this.set3dMap(this.tileLayer.google);
}
})
html部分
<section id="app" class="row no-gutters">
<div class="col-12 position-relative">
<div id="map-container"></div>
<div id="info-div">
<input class="esri-component esri-widget--button esri-widget esri-interactive"
type="button" :value="relativeDimension()" @click="toggleDimension()">
</div>
<ul id="layer-toggle-button-container" class="unstyled-list">
<li class="layer-toggle-button text-center p-0 mx-1 row" @click="selectTileLayer(layer)" v-for="layer in tileLayer" v-if="layer!=activeLayer">
<small class="font-weight-light w-100 text-center py-1">{{ layer.name }}</small>
<div class="w-100"></div>
<img :src="layer.img" class="img-fluid w-100">
</li>
</ul>
</div>
</section>
css部分:
*{
outline: none;
}
html,body{
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#map-container{
height: 500px;
}
#info-div{
position: absolute;
top: 15px;
left: 60px;
}
#info-div input {
border: none;
box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 2px;
}
#layer-toggle-button-container{
position: absolute;
top: 15px;
right: 15px;
z-index: 9;
}
#layer-toggle-button-container li{
float: right;
}
.layer-toggle-button{
width: 75px;
border: none;
box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 2px;
background-color: #fff;
color: #6e6e6e;
padding: 0;
margin: 0;
overflow: hidden;
cursor: pointer;
text-align: center;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
transition: background-color 125ms ease-in-out;
}
.layer-toggle-button:hover{
background-color: #f0f0f0;
color: #2e2e2e;
}