ArcGIS API for JavaScript+vue系列(四)-自行封装类似于百度地图中的底图切换(basemapGallery)功能

一、背景与思考

在ArcGIS API的widgets中,有一个basemapGallery的底图切换功能,但是该功能占据的空间过大,且不够美观,所以尝试利用vue自行封装一个底图切换功能。

百度地图的底图切换功较为优秀,切换功能置于地图页面的右下角,且当鼠标未悬于切换图层上时不会展示其他的切换图层,该展示的方式既美观又不过分的占据地图的空间,所以参照此功能来封装我们的底图切换功能。

在这里插入图片描述
在封装该功能之前,我们需要需要分析一下该功能的组成部分。首先在地图页面的右下角有一个浅白色的大盒子,在这个大盒子里面存放了几个小盒子,每个小盒子可以点击,点击后会切换底图。且一开始只有第一个小盒子是显示的,鼠标移动到第一个小盒子上时,其他的小盒子才显示。每一个小盒子都有其独特的标题,图片等内容。

随后,我们还应该知道,封装的组件应该可以在不同的项目中使用,所以基本的要素不应该写死,而是在具体使用过程中,从调用的父组件中传入过来,所以需要设计从父组件中传入数据的数据结构。

首先,传入的数据应该是一个数组,数组中一个数据对应一个可以切换的底图要素。所以一个底图要素是一个对象。在这个对象内,存放一个底图要素所必须的属性。需要一个标题,所以给一个属性title。需要一个用于展示的图片,使用img。然后需要给一个属性id,这个的目的主要是为了区分数组的第一个要素,因为第一个要素一开始就展示在页面中,不同于其他要素,所以使用id来区分。随后需要一个url来确定需要切换底图的url信息,当然,如果传入一个url,那也一定要传入一个该图层的类型,所以再给一个type。

最后,我们确定了该数据的数据结构,该数据是一个数组,其中具有多个对象,一个对象中有[id,title,img,url,type]五个属性,且传入的这五个属性都不能为空,可以在后台数据库中对该数据进行约束。数据结构设计完毕后,就可以开始组件的封装了。

二、封装MapSwitch文件

新建一个vue文件,命名为“MapSwitch.vue“,在template中首先定义一个大盒子div。其class为"map-switch",然后给外层盒子设置css代码。

  /* 外层盒子的css设置 */
  .map-switch{
    position: absolute;
    bottom: 10px;
    right: 10px;
    height: 70px;
    display: flex;
    justify-content: space-between;
    flex-direction: row-reverse;
    align-items: center;
    padding: 0px 5px;
  }

该盒子应该浮于地图上方,所以给定位为absolute,处于右下角,bottom和right都为10px。高度给了一个70px,没有给宽度,因为宽度会根据数组的长度动态赋予。布局方式为flex布局,justify-content设置为space-between,flex-direction设置为row-reverse,从右向左依次排放。align-items为center,设置居中对齐。最后设置上下padding为0,左右为5px。

但是map-switch一开始并不显示,所以给该盒子一个动态的class并命名为“switch-activated”,该class应该动态绑定给该盒子。如果想要展示大盒子,只需要将isShow的值改为true即可。css代码中给该盒子一个颜色。

<div :class="{'switch-activated': isShow}"></div>

import {ref} from 'vue'
  const isShow = ref(false)
    
  .switch-activated{
    background-color: #fff;
  }

大盒子的长度需要根据数组的数量来动态的设置,设置每个小盒子的长度为85px,小盒子与小盒子之间的间距为5px。根据数组长度计算大盒子的长度,并赋值给style。

    //根据数组的长度动态展示地图切换的长度
    <div :style="dynamicwidth"></div>
    
    const switchwidth = 90*props.BasemapData.length+'px'
    const dynamicwidth = {
      width: switchwidth
    }

小盒子的默认为隐藏状态,此处没有给小盒子背景图片,而是用背景颜色替代了。可根据自己的需求自行修改

/* 小盒子的基本框架 */
  .map-switch div{
    display: inline;
    width: 85px;
    height: 60px;
    background-color: skyblue;
    position: relative;
    visibility:hidden;
    z-index: 8;
  }

三、封装MapSwitchItem文件

新建一个“MapSwitchItem.vue”文件,MapSwitch中遍历BasemapData数组,该数据是存放切换地图数据的数组。随后将item对象传给MapSwitchItem文件。在MapSwitchItem文件中,最外层的div有一个动态class,来区别首个底图并显示。并在div盒子中存放标题和图片。

    //判断是否是第一个数组,第一个数组是需要展示的
    <div :class="{'base-switch': isFirst}">
      <span>{{item.title}}</span>
      <img :src="item.img" alt="">
    </div>
    
    import { computed} from 'vue'
    const isFirst = computed(() =>{
      return props.item.id === 0
    })

随后还需要添加上两个事件,一个是点击事件,点击小盒子后切换相应的底图,该事件需要传入一个参数,点击的是哪一个事件。另一个是mouseover事件,当鼠标移动到第一个盒子上时会执行该事件。

  <div @mouseover="showBasemap" @click="switchClick(item.id)"></div>
    //鼠标浮于地图切换上方时,展示所有可切换的地图
    const showBasemap = () => {
      context.emit('showBasemap')
    }
    //点击可切换底图
    const switchClick = (index) => {
      context.emit('switchClick',index)
    }

在MapSwitch文件中处理这些事件。showBasemap事件中,只需要将isShow.value改为true即可。而switchClick事件中,需要根据传入的id值来进行底图的获取。

    const showBasemap = () =>{
      isShow.value = true
    }
    const map = inject('map')
    //根据底图不同切换地图
    const switchClick = (index) =>{
      const switchitem = props.BasemapData[index]
      switch(props.BasemapData[index].type){
        //矢量图层
        case 'feature':
          map.basemap.baseLayers = [
              new FeatureLayer({
                url: switchitem.url
              })
          ]
          break;
        //影像图层
        case 'imagery':
          map.basemap.baseLayers = [
              new ImageryLayer({
                url: switchitem.url
              })
          ]
          break;
        //切片图层
        case 'tile':
          map.basemap.baseLayers = [
            new TileLayer({
              url: switchitem.url
            })
          ]
          break;
        //三维图层
        case 'scene':
          map.basemap.baseLayers = [
            new SceneLayer({
              url: switchitem.url
            })
          ]
          break
      }
    }

四、代码展示

MapSwitch.vue的代码如下:

<template>
  <div class="map-switch" :class="{'switch-activated': isShow}" @mouseleave="unShowBasemap" :style="dynamicwidth">
    <switch-map-item v-for="(item,index) in BasemapData" 
                      :key="index" 
                      :item="item" 
                      @showBasemap="showBasemap"
                      @switchClick="switchClick">
    </switch-map-item>
  </div>
</template>

<script>
import {ref, inject} from 'vue'
import SwitchMapItem from './SwitchMapItem.vue'
import TileLayer from '@arcgis/core/layers/TileLayer'
import FeatureLayer from '@arcgis/core/layers/FeatureLayer'
import ImageryLayer from '@arcgis/core/layers/ImageryLayer'
import SceneLayer from '@arcgis/core/layers/SceneLayer'
export default {
  components: { SwitchMapItem },
  props:{
    BasemapData: {
      type: Array,
      require: true
    }
  },
  setup (props) {
    const showBasemap = () =>{
      isShow.value = true
    }
    const unShowBasemap = () =>{
      isShow.value = false
    }
    const map = inject('map')
    //根据底图不同切换地图
    const switchClick = (index) =>{
      const switchitem = props.BasemapData[index]
      switch(props.BasemapData[index].type){
        //矢量图层
        case 'feature':
          map.basemap.baseLayers = [
              new FeatureLayer({
                url: switchitem.url
              })
          ]
          break;
        //影像图层
        case 'imagery':
          map.basemap.baseLayers = [
              new ImageryLayer({
                url: switchitem.url
              })
          ]
          break;
        //切片图层
        case 'tile':
          map.basemap.baseLayers = [
            new TileLayer({
              url: switchitem.url
            })
          ]
          break;
        //三维图层
        case 'scene':
          map.basemap.baseLayers = [
            new SceneLayer({
              url: switchitem.url
            })
          ]
          break
      }
    }
    //根据数组的长度动态展示地图切换的长度
    const switchwidth = 90*props.BasemapData.length+'px'
    const dynamicwidth = {
      width: switchwidth
    }
    const isShow = ref(false)
    
    return {
      showBasemap,
      unShowBasemap,
      switchClick,
      isShow,
      dynamicwidth,
    }
  }
}
</script>

<style>
  /* 外层盒子的css设置 */
  .map-switch{
    position: absolute;
    bottom: 10px;
    right: 10px;
    /* width: 800px; */
    height: 70px;
    display: flex;
    justify-content: space-between;
    flex-direction: row-reverse;
    align-items: center;
    padding: 0px 5px;
  }
  /* 小盒子的基本框架 */
  .map-switch div{
    display: inline;
    width: 85px;
    height: 60px;
    background-color: skyblue;
    position: relative;
    visibility:hidden;
    z-index: 8;
  }
  /* 第一个小盒子可见 */
  .map-switch .base-switch{
    visibility: inherit;
  }
  /* 鼠标移动到第一个盒子上所有盒子可见 */
  .switch-activated div{
    visibility: inherit;
  }
  /* 选择小盒子时添加外边框 */
  .switch-activated div:hover{
    border: .6px solid blue;
  }
  .switch-activated{
    background-color: rgb(255, 255, 255,.6);
  }
  .map-switch span{
    font-size: 12px;
    color: #fff;
    position: absolute;
    bottom: 3px;
    right: 2px;
  }
</style>

MapSwitchItem.vue的代码如下:

<template>
  <div @mouseover="showBasemap" :class="{'base-switch': isFirst}" @click="switchClick(item.id)">
    <span>{{item.title}}</span>
    <img :src="item.img" alt="">
  </div>
</template>

<script>
import { computed} from 'vue'
export default {
  props: {
    item: {
      type: Object
    }
  },
  setup (props,context) {
    //鼠标浮于地图切换上方时,展示所有可切换的地图
    const showBasemap = () => {
      context.emit('showBasemap')
    }
    //点击可切换底图
    const switchClick = (index) => {
      context.emit('switchClick',index)
    }
    //判断是否是第一个数组,第一个数组是需要展示的
    const isFirst = computed(() =>{
      return props.item.id == 0
    })
    return {
      isFirst,
      showBasemap,
      switchClick
    }
  }
}
</script>

可以展示的效果如下图所示
在这里插入图片描述

五、不足

该代码的不足之处在于没有添加背景图片进行测试,同时缺少动画效果,这些缺陷会在后期补足。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: ArcGIS API for JavaScript Vue是一种基于Vue.js框架的ArcGIS API for JavaScript封装。它提供了一种简单的方式来使用ArcGIS API for JavaScript来创建交互式地图应用程序。Vue.js是一个流行的JavaScript框架,它提供了一种简单的方式来构建动态Web应用程序。ArcGIS API for JavaScript是一个强大的地图API,它提供了许多功能,包括地图显示、地理编码、地理处理、空间分析等。ArcGIS API for JavaScript Vue结合了这两个技术,使得开发人员可以更容易地创建高质量的地图应用程序。 ### 回答2: ArcGIS API for JavaScript Vue是通过Vue.js框架集成ArcGIS API for JavaScript库而创建的Web地图应用程序。ArcGIS API for JavaScript是Esri创建的专业地理信息系统(GIS)工具之一,它提供了一组开发工具和API,可用于构建基于Web的地图应用程序。这个JavaScript库提供了强大的GIS功能,例如图层控制、地理编码、地图分析和视觉化等。 Vue.js是一个流行的JavaScript框架,可用于开发单页面应用程序(SPA)。它通过其灵活性、组件架构和简单性而获得了许多Web开发人员的喜爱。通过将ArcGIS API for JavaScriptVue.js集成,可以创建强大的Web地图应用程序,用户可以轻松地在任意设备上浏览。Vue.js的便利性使得用户可以更容易地构建交互式应用程序,同时ArcGIS API for JavaScript的GIS功能则增强了应用的功能性。 使用ArcGIS API for JavaScript Vue可以快速开发高质量的Web地图应用程序,同时不需要编写大量的代码。使用Vue.js的组件系统,您可以构建可重用的UI组件,并轻松地将它们嵌入到应用程序ArcGIS API for JavaScript提供了广泛的可定制选项,包括地图、图层、标注、符号和样式,以及可用于构建自定义GIS应用程序的分析和工具。 总之,ArcGIS API for JavaScript Vue提供了一个强大的工具箱,可用于轻松构建GIS应用程序。通过集成ArcGIS API for JavaScript库和Vue.js框架,用户可以快速构建交互式Web地图,并拥有全面的GIS功能。这个工具包使开发人员可以更快地构建出高质量的地图应用程序,同时为用户提供更好的地理定位和分析信息。 ### 回答3: ArcGIS API for JavaScript 是一款基于JavaScript开发的Web GIS 应用程序的应用程序界面,用于构建交互式的2D和3D地理信息系统应用。Vue是一种高效、轻量级的JavaScript框架,用于构建用户界面。ArcGIS API for JavaScriptVue结合使用,可以构建出高效、美观、交互性强、且地理定位准确的Web应用。 使用ArcGIS API for JavaScriptVue结合开发Web应用,可以拥有强大的先进的地图显示功能,包括可以定制地图图层演示、控制地图层级、专业组件自定义开发和地理信息分析。同时,Vue具有非常简单和有效的模板语法,结合ArcGIS API for JavaScript通用的开发用途,使用VueAPI,你可以轻松快速地构建出美观并且易于使用的Web应用。 使用ArcGIS API for JavaScriptVue结合开发Web应用还可以实现以下功能: 1. 数据可视化:可以将空间数据可视化,在地图上演示图层组成,从而增强WebGIS应用的交互性。 2. 地理定位功能:使用ArcGIS API 强大的地理定位技术,可以将地图与数据融合,从而实现地理定位功能。 3. 可自定义的组件:结合Vue框架,可以通过组件化开发,根据需要定制个性化的组件,从而提高WebGIS应用的易用性和效率。 4. 强大的分析能力:使用ArcGIS API强大的地理信息分析功能,可以在地图上展示复杂的地理信息数据。 总之,使用ArcGIS API for JavaScriptVue结合注意来构建交互性强、地理定位准确的WebGIS应用,进一步使用户体验更加优化,对地理信息的处理能力更加升级,展示效果也更加优异,具有很好的推广价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值