arcgis for js 4.X自定义气泡点击地图对象弹出对话框

题目的意思是,arcgis for js 4.X自定义气泡,点击地图对象弹出对话框,而不是弹出气泡。对话框是vue页面组成的自定义对话框,不是地图页面的对象。
在这里插入图片描述

基本思路:
1)气泡模板(PopupTemplate)的内容类型设为函数
2)该函数向地图页面的父页面发送消息,然后关闭气泡
3)地图页面的父页面接收到消息后,弹出对话框

整个过程,气泡一闪而过,甚至根本无法察觉,就好像点击地图对象,直接弹出了对话框。

在arcgis for js 3.X时代,类似的功能我也搞过,原理为气泡内容是一个iframe,在iframe页面触发对话框弹出,然后关闭气泡。相关文章:
arcgis for js 3.X通用百变气泡解决方案

在arcgis for js 4.X,也可以这么搞。但iframe嵌入的页面(是一个VUE页面)有个身份验证问题,就想采用消息通知的机制,可能更灵活些。

上代码:

1、地图页面

//popupTemplate.content可以是一个函数,有意思:
var popupIt = _getPopup(mapView, function (name) {
    //弹出对话框
    _emit({
      target: "bathPop",
      data: {
        name: name,
      },
    });
});

//定义气泡等  
var options = {
  id: "起一个好记的名字",
  url: "地图服务地址",
  sublayers: [//4.X的ImageMapLayer,也就是3.X的动态图层ArcGISDynamicMapServiceLayer
    {
      id: 31,//地图服务某子图层的ID
      outFields: ["*"],
      popupTemplate: {
        title: "{name}",
        content: popupIt,//这是上面定义的函数
      },
    },
  ],
};

_addLayer(mapView, options);

function _addLayer(mapView, options) {
  require(["esri/layers/MapImageLayer"], function (MapImageLayer) {
    var layer = new MapImageLayer(options);
    mapView.map.add(layer);
  });
}
function _emit(json) {
  //地图是用iframe嵌入到vue页面的,因此要通知vue
  //postMessage只负责发送消息,不传递数据。如果要传递数据,只能自己序列化成字符串,放在第一个参数
  window.parent.postMessage(JSON.stringify(json), "*");
}
function _getPopup(mapView, callback) {
  return function () {
    new Promise(function (resolve) {
      var timer1 = setInterval(function () {
      	//需要获得被点击地图对象的信息
      	//为了保证能获取到,使用了定时器,直到获取成功才转到下一步,否则循环等待
      	//应该还有其他更好的途径,但我还不知道
        if (!mapView.popup.content.title || mapView.popup.content.title === "") {
          return;
        }
        clearInterval(timer1);//清除定时器
        if (callback && typeof callback === "function") {
          callback(mapView.popup.content.title);
        }
        resolve();//转向下一步
      }, 200);
    }).then(function () {//这就是所谓的下一步
      mapView.popup.close();
    });
  };
}

2、地图页面的父页面

<template>
  <page-container navi="map" noFooter="true">
    <iframe
      ref="mapIframe"
      src="地图页面"
      class="mapIframe"
      frameborder="0"
      scrolling="false"
      allowfullscreen="true"
    />
  </page-container>
  <pop></pop>
</template>

<script setup>
import { ref, onMounted, nextTick } from "vue";

const init = () => {
  //监听消息
  window.addEventListener("message", popIt.bind(this));

  function popIt(ev) {
    const data = ev.data;
    try {
      if (data && data.indexOf("{") === 0) {//是json
        //弹出对话框
      }
    } catch (ex) {
      console.log(ex);
    }
  }
};

onMounted(() => {
  nextTick(() => {
    init();
  });
});
</script>

<style scoped>
.mapIframe {
  width: 100%;
  height: calc(100vh - 50px);
}
</style>

posted on 2022-12-07 22:32  左直拳  阅读(0)  评论(0)    收藏  举报  来源

导航