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

  • Before

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

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

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

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

Vue---组件实例之$el

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

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

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

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

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

js 复制代码
 
<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>

弹框组件代码:

js 复制代码
<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组件的形式,使弹框里面的功能实现分离,大大提高了拓展性,由于组件的响应式特征,我们对于弹框内容的自定义性也更好把握,最主要的是,代码写起来方便了。

相关推荐
HEX9CF16 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
凌云行者28 分钟前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻44 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江1 小时前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
___Dream1 小时前
【黑马软件测试三】web功能测试、抓包
前端·功能测试
金灰1 小时前
CSS3练习--电商web
前端·css·css3
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
Tandy12356_1 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
TonyH20021 小时前
webpack 4 的 30 个步骤构建 react 开发环境
前端·css·react.js·webpack·postcss·打包
你会发光哎u1 小时前
Webpack模式-Resolve-本地服务器
服务器·前端·webpack