mapboxGL列表和地图联动

Posted 牛老师讲GIS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mapboxGL列表和地图联动相关的知识,希望对你有一定的参考价值。

概述

列表和地图联动是webgis中一个非常常见的功能,本文讲一下在mapboxGL中结合vue如何实现此功能。

效果

实现思路

1. 获取数据

获取数据并将数据保存起来;

2. 列表展示

列表简单的用ulli来实现。

3. 地图展示

数据获取之后,通过document.createElement()的方式创建marker,将结果在地图上展示。

4. 列表地图联动

联动存在两个交互:鼠标移动和点击选中,所以需要两个变量用来记录当前鼠标经过的和点击选中的,如果鼠标经过的和点击选中发生变化的时候,去设置对应的样式即可。

实现代码

<template>
  <div class="search-panel">
    <div
      class="search-result">
    <h4 class="title">
      查询结果
    </h4>
    <ul
      class="result-list">
      <li
        v-for="(item, index) in searchResult"
        :key="index"
        :class="getClass(item)"
        @mouseover="currentMarker = item"
        @mouseout="currentMarker = "
        @click="selectMarker = item">
        <div class="marker">
          <span> index + 1 </span>
        </div>
        <div class="info">
          <b> item.name </b><br>
           item.addr 
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default 
  name: 'Search',
  data() 
    return 
      searchResult: [], //记录查询结果
      markers: [],
      currentMarker: ,
      selectMarker: ,
      markerPopup: null
    ;
  ,
  methods: 
    init() 
      this.markerPopup = new mapboxgl.Popup(
        closeButton: false,
        closeOnClick: false,
        className: 'marker-popup',
        offset: [0, -15],
        anchor: 'bottom'
      );
      // 造测试数据
      this.searchByKeyword();
    ,
    getRandomPos() 
      const bbox = [79.740682, 20.10212, 134.0345, 44.8279];
      const lon = Math.random() * (bbox[2] - bbox[0] + 1) + bbox[0];
      const lat = Math.random() * (bbox[3] - bbox[1] + 1) + bbox[1];
      return [lon, lat];
    ,
    getClass(item)  // 设置列表样式
      let cls = item.id === this.currentMarker.id ? 'active' : '';
      cls += item.id === this.selectMarker.id ? ' select' : '';
      return cls;
    ,
    setMarkersClass()  // 设置地图marker样式
      this.searchResult.forEach(item => 
        const dom = document.getElementById(item.id);
        if (item.id === this.currentMarker.id) 
          dom.classList.add('active');
         else 
          dom.classList.remove('active');
        
        if (item.id === this.selectMarker.id) 
          dom.classList.add('select');
         else 
          dom.classList.remove('select');
        
      );
    ,
    searchByKeyword() 
      const that = this;
      if (this.keyword !== '') 
        that.loading = true;
        that.searchResult = [];
        this.removeMarkers();
        setTimeout(() => 
          for (let i = 0; i < 10; ++i) 
            that.searchResult.push(
              id: 'marker' + i,
              name: '大石地铁站',
              addr: '广东省广州市番禺区大石地铁站',
              pos: that.getRandomPos()
            );
          
          // 添加markers
          that.addMarkers2Map();
          that.loading = false;
        , 2000);
      
    ,
    addMarkers2Map() 
      const that = this;
      const map = window.map;
      that.searchResult.forEach((item, index) => 
        const ele = document.createElement('div');
        ele.setAttribute('class', 'map-marker');
        ele.setAttribute('id', item.id);
        ele.innerText = (index + 1).toString();
        const option = 
          element: ele
        ;
        const marker = new mapboxgl.Marker(option)
          .setLngLat(item.pos)
          .addTo(map);
        that.markers.push(marker);

        ele.onmouseover = () => 
          that.currentMarker = item;
        ;
        ele.onmouseout = () => 
          that.currentMarker = ;
        ;
        ele.onclick = () => 
          that.selectMarker = item;
        ;
      );
    ,
    removeMarkers() 
      this.markers.forEach(marker => 
        marker.remove();
      );
    ,
    showMarkerInfo() 
      const that = this;
      if (this.selectMarker.id) 
        const description = `
            <h5>
               $this.selectMarker.name
               <span class="close el-icon-close" id="popupClose"></span>
            </h5>
            <ul>
              <li>温度: 20℃</li>
              <li>湿度: 52%</li>
              <li>降水: 1mm</li>
              <li>风速: 4m/s</li>
              <li>风向: 无持续风向</li>
            </ul>
          `;
        this.markerPopup
          .setLngLat(this.selectMarker.pos)
          .sethtml(description)
          .addTo(window.map);
        // 添加关闭事件
        document.getElementById('popupClose').onclick = () => 
          that.selectMarker = ;
        ;
        window.map.flyTo(
          center: this.selectMarker.pos
        );
       else 
        this.markerPopup.remove();
      
    
  ,
  watch: 
    currentMarker(val) 
      this.setMarkersClass();
    ,
    selectMarker(val) 
      this.setMarkersClass();
      this.showMarkerInfo();
    
  
;
</script>

<style scoped lang="scss">
@import '../../assets/css/map';
.search-panel 
  position: absolute;
  top: $padding;
  left: $padding;
  z-index: 99;
  .search-result 
    width: 315px;
    background-color: $bg-color;
    border-radius: 4px;
    padding-bottom: 10px;
    .title 
      margin: 0;
      padding: 10px;
      border-bottom: 1px solid #ccc;
      i 
        float: right;
        font-size: 14px;
        &:hover,
        &.active 
          cursor: pointer;
          color: $active-color;
          text-decoration: underline;
        
      
    
  
  .result-list 
    margin: 10px 0;
    min-height: 100px;
    li 
      padding: 8px 10px;
      overflow: hidden;
      border-bottom: 1px dashed #ddd;
      &:hover,
      &.active,
      &.select 
        cursor: pointer;
        .marker span 
          background-image: url('../../assets/images/marker-blue.png');
        
      
      &.select 
        background-color: rgba(0, 0, 0, 0.05);
      
      .marker 
        float: left;
        width: 35px;
        text-align: center;
        line-height: 30px;
        span 
          width: 26px;
          height: 26px;
          line-height: 20px;
          text-align: center;
          display: inline-block;
          background-image: url('../../assets/images/marker-red.png');
          background-size: 100%;
          color: white;
          border-radius: 100%;
        
      
      .info 
        float: left;
      
    
  

</style>
<style lang="scss">
@import '../../assets/css/map';
.map-marker 
  width: 26px;
  height: 26px;
  line-height: 20px;
  text-align: center;
  background-image: url('../../assets/images/marker-red.png');
  background-size: 100%;
  color: white;
  border-radius: 100%;
  cursor: pointer;
  &:hover,
  &.active,
  &.select 
    background-image: url('../../assets/images/marker-blue.png');
  

.marker-popup 
  color: white;
  .mapboxgl-popup-content 
    background-color: $black65;
    margin: 0;
    padding: 8px;
    white-space: nowrap;
    font-size: 12px;
    h5 
      margin: 0 0 3px 0;
      padding: 3px 0;
      font-size: 14px;
      span 
        float: right;
        cursor: pointer;
      
    
    label 
      display: inline-block;
      text-align: right;
      width: 65px;
    
  
  .mapboxgl-popup-tip 
    border-top-color: $black65 !important;
  

  .mapboxgl-popup-close-button 
    color: white;
  

</style>

以上是关于mapboxGL列表和地图联动的主要内容,如果未能解决你的问题,请参考以下文章

python3使用matplotlib绘制风速风向玫瑰图

EChart绘制风速风向曲线分析图

Excel中有日期(一年365天)、时间(一天24小时)、风速、风向、温度、辐照等数据,现在我要计算

origin玫瑰风向图如何改为大小

ORIGIN 怎么画 风向玫瑰图 呢?

风玫瑰图怎么画