博客 / 詳情

返回

騰訊地圖實現點擊marker彈複雜窗口

實現效果

image.png

存在問題

InfoWindow採用騰訊地圖官方案例,實現複雜的界面會比較複雜,而且不利於維護。
image.png

代碼實現

前端代碼

<div class="screen-map-container">
  <div id="tencentMapContainer" class="screen-bm-view"></div>
  <div ref="customOverlay" class="mapItemInfo">
      <el-button class="map-item-info-close" @click="mapItemInfoClose"></el-button>
      <div>
        <div class="statistics-container">
          <span style="position:absolute;left:0.27rem;font-weight: bold;color: #FFFFFF">{{mapItemInfoTitle}}</span>
          <div class="statistics-item" style="margin-left: 0.25rem" @click="mapItemInfoClick('all')">
            <div style="color: #FFFFFF">總數</div>
            <div class="number">{{mapInstallPointStatics.total}}</div>
          </div>
          <div class="border"></div>
          <div class="statistics-item" @click="mapItemInfoClick('online')">
            <div style="color: #06f1a8">
              <span class="point" style="border-color: #06f1a8;background: #06f1a8;"></span>在線
            </div>
            <div class="number">{{mapInstallPointStatics.online}}</div>
          </div>
          <div class="border"></div>
          <div class="statistics-item" @click="mapItemInfoClick('offline')">
            <div style="color: #d9dfdd">
              <span class="point" style="border-color: #d9dfdd;background: #d9dfdd;"></span>離線
            </div>
            <div class="number">{{mapInstallPointStatics.total-mapInstallPointStatics.online}}</div>
          </div>
          <div class="border"></div>
          <div class="statistics-item" @click="mapItemInfoClick('alarm')">
            <div style="color: #f14216">
              <span class="point" style="border-color: #f14216;background: #f14216;"></span>報警
            </div>
            <div class="number">{{mapInstallPointStatics.alarm}}</div>
          </div>
        </div>
        <div style="height: 1px;background-color: #4260c6A0;margin: 0.0625rem 0.125rem 0 0.125rem;"></div>
        <el-table v-loading="deviceLoading" :data="deviceList" style="height: 2.625rem;">
          <el-table-column label="設備編號" align="left" prop="imei"/>
          <el-table-column label="名稱"  align="left" prop="deviceName" show-overflow-tooltip/>
          <el-table-column label="在線狀態" align="left" prop="onlineState" width="80">
            <template #default="scope">
              <el-text size="small" v-if="scope.row.onlineState === 1" type="success" >在線</el-text>
              <el-text size="small" style="color: #cbd4d0;" v-else>離線</el-text>
<!--                          <el-tag size="small" color="transparent" style="color: #a6aaa8;border-color:transparent" v-else>離線</el-tag>-->
            </template>
          </el-table-column>
          <el-table-column label="設備狀態" align="left" prop="deviceState" width="80">
            <template #default="scope">
              <el-text size="small" v-if="scope.row.deviceState === 0" type="success">正常</el-text>
              <el-text size="small" v-else-if="scope.row.deviceState === 1" type="warning">故障</el-text>
              <el-text size="small" v-else type="danger">報警</el-text>
            </template>
          </el-table-column>
        </el-table>

        <pagination
            v-show="deviceTotal>0"
            :total="deviceTotal"
            size="small"
            :page-sizes="[5]"
            :background="false"
            :pager-count="3"
            v-model:page="deviceQueryParams.pageNum"
            v-model:limit="deviceQueryParams.pageSize"
            @pagination="getBoundDeviceList"
        />
      </div>
  </div>
</div>
  • <div id="tencentMapContainer" class="screen-bm-view"></div> 是地圖容器
  • <div ref="customOverlay" class="mapItemInfo"> 是彈窗界面

js

我們需要某種方式,當彈窗時動態替換windowInfo顯示的內容。關鍵代碼是:

document.querySelector(".map-info-window").append(proxy.$refs.customOverlay);
infoWindow = new TMap.InfoWindow({
  map: tencentMap,
  enableCustom: true,
  position: new TMap.LatLng(40.040422, 116.273521),
  offset: { y: 0, x: 20 },
  content:'<div class="map-info-window"></div>',
});
infoWindow.close();

map-info-window css樣式不重要,因為會被customOverlay替換掉。

.map-info-window{
    width: 300px;
    height: 300px;
}

主要關鍵代碼如下:

初始化地圖、marker圖層、彈窗

  import bdNormalPointIcon from '../../assets/images/map_point_6.png';
  import bdAlarmPointIcon from '../../assets/images/map_point_4.png';
  import bdAllOnlinePointIcon from '../../assets/images/map_point_1.png';
  import bdFaultPointIcon from '../../assets/images/map_point_2.png';
  import bdAllOfflinePointIcon from '../../assets/images/map_point_3.png';

  //騰訊地圖對象
  let tencentMap;
  //騰訊地圖點標記對象
  let markerLayer;
  //信息彈窗
  let infoWindow;
  //初始化騰訊地圖
  const initMap = () => {
    if (tencentMap) {
      console.log('地圖已初始化,不再重複初始化');
      return;
    }
    let center = new TMap.LatLng(35.79717, 104.357285);
    tencentMap = new TMap.Map(document.getElementById('tencentMapContainer'), {
      center: center,//設置地圖中心點座標
      zoom: 4.5,   //設置地圖縮放級別
      mapStyleId: 'style1', //設置地圖樣式
      showScaleVideo: false, //顯示比例尺
    });
    tencentMap.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM);
    tencentMap.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ROTATION);
    markerLayer = new TMap.MultiMarker({
      map: tencentMap,  //指定地圖容器
      //樣式定義
      styles: {
        //創建一個styleId為"myStyle"的樣式(styles的子屬性名即為styleId)
        "normal": new TMap.MarkerStyle({
          "width": 50,  // 點標記樣式寬度(像素)
          "height": 50, // 點標記樣式高度(像素)
          //焦點在圖片中的像素位置,一般大頭針類似形式的圖片以針尖位置做為焦點,圓形點以圓心位置為焦點
          "anchor": { x: 10, y: 30 },
          "src": bdNormalPointIcon
        }),
        "online": new TMap.MarkerStyle({
          "width": 50,  // 點標記樣式寬度(像素)
          "height": 50, // 點標記樣式高度(像素)
          //焦點在圖片中的像素位置,一般大頭針類似形式的圖片以針尖位置做為焦點,圓形點以圓心位置為焦點
          "anchor": { x: 10, y: 30 },
          "src": bdAllOnlinePointIcon
        }),
        "offline": new TMap.MarkerStyle({
          "width": 50,  // 點標記樣式寬度(像素)
          "height": 50, // 點標記樣式高度(像素)
          //焦點在圖片中的像素位置,一般大頭針類似形式的圖片以針尖位置做為焦點,圓形點以圓心位置為焦點
          "anchor": { x: 10, y: 30 },
          "src": bdAllOfflinePointIcon
        }),
        "alarm": new TMap.MarkerStyle({
          "width": 50,  // 點標記樣式寬度(像素)
          "height": 50, // 點標記樣式高度(像素)
          //焦點在圖片中的像素位置,一般大頭針類似形式的圖片以針尖位置做為焦點,圓形點以圓心位置為焦點
          "anchor": { x: 10, y: 30 },
          "src": bdAlarmPointIcon
        }),
      },
      //點標記數據數組
      geometries: []
    });
    markerLayer.on('click',(e)=>{markerClick(e)});
    infoWindow = new TMap.InfoWindow({
      map: tencentMap,
      enableCustom: true,
      position: new TMap.LatLng(40.040422, 116.273521),
      offset: { y: 0, x: 20 },
      content:'<div class="map-info-window"></div>',
    });
    infoWindow.close();
  }

添加marker

function requestInstallPoint(){
  listScreenInstallPoint(installPointQueryParams).then(response => {
    installPointList.value = response.rows;
    //清除標記點
    markerLayer.setGeometries([]);
    installPointList.value.forEach(item=>{
      addMaker(item);
    });
  });
}

function addMaker(item) {
    let markerId = item.id;
    if (item.deviceStatisticsDto.online === 0) {
      markerLayer.add([{
        "id": markerId,   //點標記唯一標識,後續如果有刪除、修改位置等操作,都需要此id
        "styleId": 'offline',  //指定樣式id
        "position": new TMap.LatLng(item.latitude,item.longitude),  //點標記座標位置
      }]);
    }else if (item.deviceStatisticsDto.alarm > 0) {
      markerLayer.add([{
        "id": markerId,   //點標記唯一標識,後續如果有刪除、修改位置等操作,都需要此id
        "styleId": 'alarm',  //指定樣式id
        "position": new TMap.LatLng(item.latitude,item.longitude),  //點標記座標位置
      }]);
    }else if(item.deviceStatisticsDto.online === item.deviceStatisticsDto.total){
      markerLayer.add([{
        "id": markerId,   //點標記唯一標識,後續如果有刪除、修改位置等操作,都需要此id
        "styleId": 'online',  //指定樣式id
        "position": new TMap.LatLng(item.latitude,item.longitude),  //點標記座標位置
      }]);
    }else {
      markerLayer.add([{
        "id": markerId,   //點標記唯一標識,後續如果有刪除、修改位置等操作,都需要此id
        "styleId": 'normal',  //指定樣式id
        "position": new TMap.LatLng(item.latitude,item.longitude),  //點標記座標位置
      }]);
    }
  }

彈窗顯示和關閉

function markerClick(e) {
    console.log('marker click-------------->', e);
    let markerId = e.geometry.id;
    //let position = e.geometry.position;
    let installPoint  = installPointList.value.find(item => item.id === markerId);

    markerPosition.value.lat= installPoint.latitude;
    markerPosition.value.lng= installPoint.longitude;

    deviceQueryParams.installId = installPoint.id;
    deviceQueryParams.pageNum = 1;
    deviceQueryParams.onlineState = null;
    deviceQueryParams.deviceState = null;
    getBoundDeviceList();

    mapItemInfoTitle.value = installPoint.installName;
    getInstallPointDeviceStatistics(installPoint.id).then(response => {
      mapInstallPointStatics.value = response.data;
    });

    document.querySelector(".map-info-window").append(proxy.$refs.customOverlay);
    infoWindow.setPosition(new TMap.LatLng(installPoint.latitude, installPoint.longitude));
    infoWindow.open();
  }

  function mapItemInfoClose(){
    infoWindow.close();
  }
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.