vue + arcgis for javascript 实战(二)实现底图切换,经纬度显示等

好了,我们继续给我们的地图进行配置
现在path:src/utils文件夹加入一个EsriConfig.js文件,我们将option和Modules移入进入然后导出。
并且在path:computents/Map/index文件中导入
import { Option, Modules } from "@/utils/EsriConfig";
此时,就将模块抽离开了。
注意,现在option成了大写
export const Option = {
  url: "https://js.arcgis.com/4.15/init.js",
  css: "https://js.arcgis.com/4.18/esri/themes/light/main.css"
};
export const Modules = [
  "esri/Map",
  "esri/Basemap",
  "esri/views/MapView",
  "esri/layers/BaseTileLayer",
  "esri/Color",
  "esri/request",
  "esri/Graphic",
  "esri/layers/GraphicsLayer",
  "esri/layers/GeoJSONLayer",
  "esri/layers/support/LabelClass",
  "esri/widgets/BasemapGallery/BasemapGalleryViewModel",
  "esri/views/draw/Draw",
  "esri/widgets/Sketch/SketchViewModel",
  "esri/widgets/ScaleBar",
];
我们上一个章节看到,我们添加了两个底图在map中。那我们就把图层切换实现了吧。
新建一个子组件vue 模板,就叫basetogle吧
这个一个同目录级别的文件,数据传递方式使用的是子传父。在里面就干一件事,点击传递切换。
<template>
  <ul class="tool">
    <li v-for="(item, index) in source" :key="index" @click.stop="togglelay(item)">
      <img :src="item.image"> <span :class="item.checked ? 'active': ''">{{item.name}}</span>
    </li>
  </ul>
</template>

<script>
//  import {} from ''
export default {
  name: "basetogle",
  data() {
    return {
      source: [
        {checked: true, value: 'google_lay' ,name: "影像图层", image: require("@/assets/img/yingxiang.jpg")},
        {checked: false, value: 'raster_lay', name: "地形图层", image: require("@/assets/img/dixing.jpg")},
        {checked: false, value: 'tmts_lay', name: "地质图层", image: require("@/assets/img/dizhitu.png")},
      ]
    };
  },

  mounted() {},

  methods: {
    togglelay(item) {
      this.$emit('togle', item)
    }
  }
  //  End
};
</script>

<style lang='stylus' scoped>
      .tool {
        position: absolute;
        top: 100px;
        right: 60px;
        background-color: #fff;
        color: #c0c4cc;
        font-size: 12px;
        width: 120px;
        height: 60px;
        overflow: hidden;
        transition: all 0.45s;
        li {
          transition: all 0.45s;
          height: 60px;
          width: 80px;
          display: inline-block;
          position: absolute;
          right: 0px;
          padding: 1px;
          img {
            width: 100%;
            height: 100%;
          }
          span {
            position: absolute;
            bottom: 3px;
            left: 3px;
          }
          .active {
            color: #fff;
          }
          &:first-child {
            right: 40px;
          }
          &:last-child {
            right: -40px;
          }
        }
        &:hover {
          overflow: unset;
          width: 220px;
          transform-style: preserve-3d;
        }
        &:hover li:nth-child(1) {
          right: 140px;
          transform: translateZ(10px);
        }
        &:hover li:nth-child(2) {
          right: 70px;
          transform: translateZ(10px);
        }
        &:hover li:nth-child(3) {
          right: 0px;
          transform: translateZ(10px);
        }
      }
</style>

1. 导入模板后加入,并绑定好方法关系,在basetogle方法中使用的方式拿到所有图层。
2. 遍历过滤,在之前封装的天地图函数方法中我们有两个属性会用到它,visible 和baselayer 。为了防止加入的图层受到影响它会为我们做最好的判断。
//template
<basetogle @togle="basetogle" ref="basetogle"></basetogle>	// 使用
// script
import basetogle from './basetogle'	//导入
// 在methods方法中注册方法
   basetogle(attr) {
      if (this.$refs.basetogle.source) {
        let source = this.$refs.basetogle.source;
        source.forEach(k => {
          if (attr.value === k.value) k.checked = true;
          else k.checked = false;
        });
      }
现在你的图层应该是这样效果。

我们现在自定义一个经纬度控件吧

新建一个子组件vue 模板,就叫bar吧。

这个组件什么事情也不做,双向绑定让他显示就行了。
<template>
  <div id="mousePosition">
      <span>经度:{{attr.x}}</span>
      <span>纬度:{{attr.y}}</span>
  </div>
</template>

<script>
//  import {} from ''
export default {
  name: "bar",
  props: ['attr'],

  mounted() {},

  methods: {}
  //  End
};
</script>

<style lang='css' scoped>
div#mousePosition {
  text-align: center;
  width: 274px;
  height: 30px;
  background-color: rgba(40, 40, 40, 0.4);
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  color: white;
  line-height: 30px;
}
div#mousePosition span:last-child {
  margin-left: 20px;
}
</style>
//template
<bar :attr="mouse"></bar>	// 使用
// script
import basetogle from './basetogle'	//导入
import bar from './bar'
// data/return 注册数据
	mouse: { x: '', y: '' },
// methods/init/Map 实例化之后
	view.on('pointer-move', this.__MouseAttr)
// methods 注册
   __MouseAttr(evt) {
     this.mouse.x = view.toMap(evt).longitude.toFixed(6);
     this.mouse.y = view.toMap(evt).latitude.toFixed(6);
   }
我们来加入比例尺控件。比例尺是用的官方的,就两个特点,简单,丑。
// methods/init/Map 实例化之后
view.ui.add(this.scaleRuler, {position: 'bottom-left'})
// comput注册属性
    scaleRuler() {  // 比例尺
      return new this.getEsri.ScaleBar({view, style: 'ruler', unit: 'metric'})
    }
接下来我们在view 添加一句代码,解决默认的样式。
// methods/init/Map 实例化之后
view.ui.components = [];
可能有人觉得双击地图时,它也会放大,怎么取消,怎么弄?这个问题问的好。我们加入这串代码即可
// methods/init/Map 实例化之后
view.on(['click', 'double-click'], e => e.stopPropagation());
// 不过加入了这个会阻止事件传递,绘制矩形图形draw对象时候无法终止操作。arcgis用的不是很溜,体验也不好

vue + arcgis for javascript 实战(二)实现底图切换,经纬度显示等_第1张图片

最后成品代码
// An highlighted block
<template>
<div class="Container">
  <div id="map"></div>
  <basetogle @togle="basetogle" ref="basetogle"></basetogle>
  <bar :attr="mouse"></bar>
</div>
</template>

<script>
const option = {
        url: "https://js.arcgis.com/4.15/init.js",
        css: "https://js.arcgis.com/4.18/esri/themes/light/main.css"
      };
const Modules = [
  "esri/Map",
  "esri/Basemap",
  "esri/views/MapView",
  "esri/request",
  "esri/layers/BaseTileLayer",
];
let map, view;
import { loadModules } from "esri-loader";
import { Option, Modules } from "@/utils/EsriConfig";
import { mapState, mapMutations, mapGetters } from 'vuex'
import { TintLayer } from './Baselayer'	// 导入自定义的天地图对象文件。
import basetogle from './basetogle'
import bar from './bar'
export default {
  name: "index",
  components: { bar, basetogle },
  data() {
    return {
		mouse: { x: '', y: '' },
    };
  },

  mounted() {
    this.init();
  },

  methods: {
    init() {
      loadModules(Modules, option).then(this.setModule).then(this.initMap);
    },
    setModule(args) {
      let esri = {};
      for (let k in args) {
	    let name = Modules[k].split("/").pop();
	    esri[name] = args[k];
      }
      this.setEsri(esri);
    },
    initMap() {
      const google_lay = TintLayer({
          url: 'http://mt0.google.cn/vt/lyrs=t,r&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}',
          id: 'google_lay',
          visible: true,
          baselayer: true,
          store: this.getEsri
        });
      const raster_lay = TintLayer({
          url: 'http://mt0.google.cn/vt/lyrs=s@702&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}&s=Ga',
          id: 'raster_lay',
          visible: false,
          baselayer: true,
          store: this.getEsri
        });
      const basemap = new this.esri.Basemap({ baseLayers: [google_lay, raster_lay] });
      map = new this.esri.Map({ basemap });
      view = new this.esri.MapView({
        container: "map",
        map,
        center: [114, 30],
        zoom: 6
      });
   	  view.on(['click', 'double-click'], e => e.stopPropagation()); // 清除默认双击放大事件
      view.ui.add(this.scaleRuler, {position: 'bottom-left'})
      view.ui.components = [];
      view.on('pointer-move', this.__MouseAttr)
    },
	basetogle(attr) {
      if (this.$refs.basetogle.source) {
        let source = this.$refs.basetogle.source;
        source.forEach(k => {
          if (attr.value === k.value) k.checked = true;
          else k.checked = false;
        });
      }
      const layers = map.allLayers.items;
      layers.forEach(v => {
        if (attr.value === v.id && v.baselayer) v.visible = true;
        else if (attr.value !== v.id && v.baselayer) v.visible = false;
      })
    },
    __MouseAttr(evt) {
      this.mouse.x = view.toMap(evt).longitude.toFixed(6);
      this.mouse.y = view.toMap(evt).latitude.toFixed(6);
    },
  },
  computed: {
   	scaleRuler() {  // 比例尺
      return new this.getEsri.ScaleBar({view, style: 'ruler', unit: 'metric'})
    },
    ...mapState({
      esri: state => state.map.esri,
    }),
    ...mapGetters(['getEsri'])
  },

  //  End
}
</script>

<style lang='stylus' scoped>
.Container {
  width: 100%;
  height: 100%;
  #map {
    width: 100%;
    height: 100%;
  }
}
</style>

可有有人会说地图和经纬度不是有ui微件吗,我只能说我喜欢按我的风格来设计。

你可能感兴趣的:(arcgis,vue,gis,vue,js,arcgis)