Vue2 使用天地图响应式信息窗口的一种实现方式

  • Before  

        当查看天地图中关于信息弹框的案例时,发现其实现方法是插入一 html 片段。若需要在弹框中实现较为复杂的展示或交互的时候,需要通过 内联事件 或者 操作JS 的方法实现。在项目开发中,我们可以借助项目框架自带的响应式组件处理。

  • 效果

  • 思路:通过 Vue.extend 创建一独立组件,并将实例节点挂载到天地图弹窗

若对 Vue.extend 加 $mount() 独立组件挂载的方式不熟悉,可先熟悉:

Vue中 Vue.extend() 详解及使用

Vue—组件实例之$el

这里的项目框架是 vue2 + vue-cli3,为了使效果更加突出,这里在弹框中引入了 ECharts

代码尽可能体现的实现思路,具体业务可在此基础上拓展

可将此代码粘贴至本地运行

详细说明在代码注释中体现

  • 代码

主要实现代码(直接在 app 组件里面写了)


<template>
  <!-- 天地图 -->
  <div id="app">
    <div id="map_box" class="mapbox">

    </div>
  </div>
</template>

<script>
import Vue from 'vue';
import iconPhone from "./assets/phone.svg";
import chartPop from "./components/chartPop.vue"; //引入组件实例
export default {
  name: "App",
  data() {
    return {
      map:null
    };
  },
  mounted() {
    setTimeout(() => {
      this.init();
    }, 200);

  },
  methods: {
    init() {
      // 初始化一天地图
      this.map = new T.Map("map_box", {
        // projection: "EPSG:4326",
        center: new T.LngLat(116.36783, 39.90579),
        zoom: 14,
        minZoom: 8,
        maxZoom: 18,
      });

      // 在天地图中插入一个坐标点 
      let point = {
        type: 1,
        LngLat: { lng: 116.36783, lat: 39.90579 },
        title: "天地图测试一下11111111111111111",
      }
      // 添加图片标注点
      //创建图片对象
      let icon = new T.Icon({
        iconUrl: iconPhone,
        iconSize: new T.Point(41, 50),
        iconAnchor: new T.Point(20, 50), //图标偏移,对齐
      });

      let { lng, lat } = point.LngLat;
      //向地图上添加自定义标注
      let marker = new T.Marker(new T.LngLat(lng, lat), {
        icon: icon, // 自定义图标
      });
      this.map.addOverLay(marker);

      // 在标注上添加文字标注
      let latlng = new T.LngLat(lng, lat);
      let label = new T.Label({
        text: point.title,
        position: latlng,
      });
      label.setBackgroundColor("rgba(0,0,0,0.5)");
      label.setFontColor("#fff");
      this.$nextTick(() => {
        label.setOffset(new T.Point(-label._labelWidth / 2 - 9, 15)); //这段代码是为了让文字在图标的中间位置
      });

      //创建地图文本对象
      this.map.addOverLay(label);


      // 信息窗口
      let chartPopExtend = Vue.extend(chartPop) // 创建一独立组件
      let devicePopEl = new chartPopExtend({
          data:{
              close:this.infoCallBack //关闭弹框的回调,这里我通过 data 里数据形式将函数声明传入
          },
          store:this.$store //注意通过 extend 创建独立组件的时候 store 需要传入,不然直接拿不到,若用到 route 或其他拿不到的数据,可以参考
      }) 
      let vm = devicePopEl.$mount('') // 此处不直接挂载 VM 是组件实例

      // 这里的 vm.$el 实际上就是 templete 的根元素标签
      let infoWin = new T.InfoWindow(vm.$el,{ maxHeight:400,minWidth:500,closeButton:false,autoPan:true });
      infoWin.addEventListener('open',()=>{ //当弹窗打开,调用组件的 open 函数
          vm.open()
      })
      marker.addEventListener("click",  () => {
        marker.openInfoWindow(infoWin);
      }); 
      this.marker = marker
    },

    infoCallBack(){
      this.marker.closeInfoWindow()
    }

  },
};
</script>

<style lang="less">
html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

* {
  box-sizing: border-box;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* text-align: center; */
  color: #2c3e50;
  /* margin-top: 60px; */
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  position: relative;
  box-sizing: border-box;
}

.mapbox {
  width: 1200px;
  height: 800px;
  border: 1px solid #000;
  margin: 0 auto;
}
</style>

弹框组件代码

<template>
  <div class="box">
    <div class="main" id="main"></div>
    <div class="btn">
      <button @click="close">close</button>
    </div>
  </div>
</template>
<script>
import * as echarts from "echarts";
export default {
  data() {
    return {};
  },
  created() {},
  computed: {},
  methods: {
    open() {
      var chartDom = document.getElementById("main");
      var myChart = echarts.init(chartDom);
      var option;

      option = {
        xAxis: {
          type: "category",
          data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
        },
        yAxis: {
          type: "value",
        },
        series: [
          {
            data: [120, 200, 150, 80, 70, 110, 130],
            type: "bar",
          },
        ],
      };

      option && myChart.setOption(option);
    },
    close() {
      this.infoCallBack(); // 这里调用外层传入的函数声明,关闭弹框
    },
  },
};
</script>
<style lang="less" scoped>
.box {
  width: 500px;
  height: 400px;
}
.main {
  width: 100%;
  height: 350px;
  border: 1px solid #000;
}
.btn {
  height: 40px;
  line-height: 40px;
  text-align: center;
}
</style>
  • 总结

在弹框组件里面,采用vue组件的形式,使弹框里面的功能实现分离,大大提高了拓展性,由于组件的响应式特征,我们对于弹框内容的自定义性也更好把握,最主要的是,代码写起来方便了。

  • 引用

Vue中 Vue.extend() 详解及使用_vue中vue.extend()在富文本代码中整体替换-CSDN博客

https://llljpf.blog.csdn.net/article/details/108280255?spm=1001.2101.3001.6661.1&utm_medium=dstribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7EPayColumn-1-108280255-blog-7508631.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevan_t0.none-task-blog-2%7Edefault%7ECTRLIST%7EPayColumn-1-108280255-blog-75408631.pc_relevant_3othn_strategy_and_data_recovery&utm_relevant_index=1

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值