ArcGIS API for JS + Vue 实现 2D / 3D /不同底图 的无缝切换(视图位置不发生改变)

需要用到: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;
  }

 

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值