WebGL--vue+openlayers实现覆盖物+popup

前言

最近公司有需求,需要用到openlayers实现在地图上面绘制多边形,并且轨迹回放,实现弹出框,国内资料太少了,所以在这里放上openlayers的学习教程以及这个案例的代码

基础知识的准备

openlayers中文文档:点击这里去中文文档
openlayers常用的API:点击这里去API总结处
openlayers官网:官网
//提示:用Edge可以对这个英文网站进行翻译

栗子:vue+openlayers实现覆盖物+popup

效果:
在这里插入图片描述

<!--  -->
<template>
  <div class="showOverlay">
    <div id="map"></div>
    <!-- 提示框 -->
    <div id="popup" ref="popupRef"></div>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
//引入主要组件
import { Feature, Map, Overlay, View } from "ol";
//引入layer
import ImageLayer from "ol/layer/Image";
import VectorLayer from "ol/layer/Vector";
//引入source
import Static from "ol/source/ImageStatic";
import VectorSource from "ol/source/Vector";
//其他
import Projection from "ol/proj/Projection";
import { getCenter } from "ol/extent";
import { Point } from "ol/geom";
import { Style, Icon } from "ol/style";
//import { Style, Icon, Text, Fill, Stroke } from "ol/style";
//导入图片
import mapImage from "@/assets/img/map1.jpg"; //底图
import personImg from "@/assets/img/anchor.png";

export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    //这里存放数据
    return {
      map: null, //地图
      //   imgW: 0, //图片的宽高
      //   imgH: 0,
      persons: [], //人员
      features: [], //覆盖物
      feature: null,
      vectorource: new VectorSource(), //矢量数据
    };
  },
  //计算属性 类似于data概念
  computed: {},
  //监控data中的数据变化
  watch: {
    persons(newVal) {
      if (newVal) {
        this.setFeature();
      }
    },
  },
  //方法集合
  methods: {
    //初始化地图
    initMap() {
      //限制范围
      let extent = [0, 0, 2560, 1920];
      //投影
      let projection = new Projection({
        //SRS 标识符代码,例如EPSG:4326
        code: "xkcd-image",
        //	单位。必需,除非 定义 PROJ4 投影。code
        units: "pixels",
        //SRS 的有效性范围。
        extent: extent,
      });
      //layers--图片底图
      let mapLayer = new ImageLayer({
        source: new Static({
          url: mapImage,
          projection: projection,
          imageExtent: extent,
        }),
      });
      //layer--矢量图层
      let featureLayer = new VectorLayer({
        source: this.vectorource,
      });
      //创建地图
      this.map = new Map({
        target: "map",
        layers: [mapLayer, featureLayer],
        view: new View({
          //配置投影
          projection: projection,
          //配置中心
          center: getCenter(extent),
          //配置zoom
          zoom: 2,
          //配置最大zoom
          maxZoom: 10,
        }),
      });
      //添加覆盖物
      let overlay = new Overlay({
        //OverLay元素
        element: document.querySelector("#popup"),
        //跟随平移
        autoPan: true,
        //偏移量--数组第一个元素为水平偏移,正右负左;数组第二个元素为垂直,正下负上;
        offset: [0, 2],
        //覆盖物位置
        // position: [0, 0],
      });
      this.map.addOverlay(overlay);
      //给map绑定事件
      this.map.on("pointermove", this.showPopup);
    },
    //hover显示覆盖物
    showPopup(e) {
      console.log(e);
      //   let that = this; //vue实例
      let oPopup = this.$refs.popupRef; //获取到popup元素
      //获取到图层上的feature  (pixel:像素,callback(f:根据像素返回的feature))
      let feature = this.map.forEachFeatureAtPixel(e.pixel, (f) => f);
      //   console.log(feature);
      if (feature) {
        // console.log(feature.getProperties());
        // 把对应的人的信息在popup中展示出来
        // console.log("ren", this.persons);
        this.persons.filter((item) => {
          if (item.name == feature.getProperties().name) {
            oPopup.innerHTML = `<p>姓名:${item.name}</p>`;
            // 设置popup的位置
            this.map.getOverlays().array_[0].setPosition(e.coordinate);
          }
        });
      } else {
        this.map.getOverlays().array_[0].setPosition(undefined);
      }
    },
    //设置feature人
    setFeature() {
      //   let that = this; //vue实例
      //   this.features = [];
      // this.map.getLayers();清除掉原本矢量图上的source  that.vectorSource.clear();
      //   this.vectorource.clear();
      //添加每个feature
      this.persons.map((item) => {
        this.feature = new Feature({
          geometry: new Point([item.x, item.y]),
          name: item.name,
        });
        //设置feature的样式(使用锚点)
        this.feature.setStyle(
          new Style({
            image: new Icon({
              //设置icon的锚,默认是中心[0.5,0.5]
              anchor: [0, 1],
              //设置icon的图片
              src: personImg,
            }),
            // text: new Text({
            //   // 位置
            //   textAlign: "center",
            //   // 基准线
            //   textBaseline: "middle",
            //   // 文字样式
            //   font: "normal 20px 微软雅黑",
            //   // 文本内容
            //   text: item.name,
            //   // 文本填充样式(即文字颜色)
            //   fill: new Fill({ color: "#aa3300" }),
            //   stroke: new Stroke({ color: "#ffcc33", width: 2 }),
            // }),
          })
        );
        //添加每个feature到features数组中
        this.features.push(this.feature);
      });
      //将feature添加到矢量图层去
      this.vectorource.addFeatures(this.features);
    },
  },
  beforeCreate() {}, //生命周期 - 创建之前
  //生命周期 - 创建完成(可以访问当前this实例)
  created() {
    //在此周期给persons添加数据
    this.persons = [
      { id: 1, name: "点-1", x: 497.08, y: 187.88, z: 0 },
      { id: 2, name: "点-2", x: 725.32, y: 565.88, z: 0 },
      { id: 3, name: "点-3", x: 643.24, y: 503.96, z: 0 },
    ];
  },
  beforeMount() {}, //生命周期 - 挂载之前
  //生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {
    //初始化地图
    this.initMap();
    // this.showPopup();
  },
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style scoped>
#map {
  width: 1000px;
  height: 800px;
  border: 1px solid #333;
  margin: 0 auto;
}
#popup {
  width: 200px;
  height: 80px;
  padding: 0 20px;
  border-radius: 5px;
  z-index: 1;
  opacity: 1;
  position: absolute;
  bottom: 0;
  left: 0;
  margin: 0;
  background: rgba(0, 60, 136, 0.7);
  color: white;
  border: 0;
  transition: opacity 100ms ease-in;
}
</style>
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值