Use of Vue Zhongtian map to add points, lines, areas, convergence points, information windows, customized right-click menus, and switch map layer operations

The collection encapsulates several commonly used sky map methods for your own subsequent use and for everyone to directly CV. The comments are very detailed and can be used out of the box or copied.

  • Add a single point marker

  • Information window Information window parameters + click callback

  • Add multiple point markers

  • Add point aggregation

  • Add line

  • Add polygon faces

  • Overlay right-click menu
<template>
  <div>
    <div class="tool_container">
      <button class="_btn" type="button" @click="addMarker(demoLnglat)">
        Add points
      </button>
      <button class="_btn" type="button" @click="addMarkers(demoPath)">
        Add multiple points
      </button>
      <button class="_btn" type="button" @click="addMarkerCluster()">
        Add point aggregation
      </button>
      <button class="_btn" type="button" @click="addLine(demoPath)">
        Add line
      </button>
      <button class="_btn" type="button" @click="addPolygon(demoPath)">
        Add faces
      </button>
      <button class="_btn" type="button" @click="changeLayer('BZ')">
        Switch standard layer
      </button>
      <button class="_btn" type="button" @click="changeLayer('WX')">
        Switch satellite layer
      </button>
      <button class="_btn" type="button" @click="changeLayer('WXLW')">
        Switch satellite road network layer
      </button>
      <button class="_btn" type="button" @click="changeLayer('DX')">
        Switch terrain layer
      </button>
      <button class="_btn" type="button" @click="changeLayer('DXLW')">
        Switch terrain road network layer
      </button>

      <button class="_btn" type="button" @click="clearMap()">Clear all</button>
    </div>
    <!--Tips This @contextmenu.prevent is to prevent the default right-click event on the map on the browser -->
    <div @contextmenu.prevent id="mapID" class="map_container"></div>

    <InfoWindow
      ref="infoWindow"
      v-show="showInfoWindow"
      :infoWindow="mapConfig.infoWindow"
      :data="mapConfig.infoWindowData"
      @callback="infoWindowCallback"
    ></InfoWindow>
  </div>
</template>
<script>
  import './mapTDT.min.js' //Introducing Tianmap service
  //Tips The file here is to download the server file to the local and then reference it, such as [https://api.tianditu.gov.cn/api?v=4.0 &tk=your secret key] and open it in the browser to download. Modify the file name and put it at the same level as the current file.

  import InfoWindow from './infowindow' //The information window is behind
  export default {<!-- -->
    data() {<!-- -->
      return {<!-- -->
        demoLnglat: '120.209809, 30.246587', //Simulate latitude and longitude
        // Simulate lattice array
        demoPath: [
          [120.13292, 30.2624],
          [120.16339, 30.25492],
          [120.16159, 30.23089],
          [120.13181, 30.23252],
        ],
        mapConfig: {<!-- -->
          map: null, //map container
          zoom: 10, //zoom level
          center: [120.209809, 30.246587], //default center point
          contextMenu: null, //Right-click menu
          marker: null, //point
          markers: null, //multiple points
          markerCluster: null, //point aggregation
          line: null, //line
          polygon: null, //face
          infoWindow: null, //Information window
          infoWindowData: {<!-- -->}, //Information window data
        },
        showInfoWindow: false, //Information window display
      }
    },
    components: {<!-- --> InfoWindow },
    mounted() {<!-- -->
      this.initMap() //Initialize the map
    },
    methods: {<!-- -->
      //Initialize the map
      initMap() {<!-- -->
        this.mapConfig.map = new T.Map('mapID')
        this.mapConfig.map.centerAndZoom(
          this.returnLnglat(this.mapConfig.center),
          this.mapConfig.zoom
        )
        this.initMapAfter() //Method after loading the map
      },
      //Operation after initializing the map
      initMapAfter() {<!-- -->
        //to do something
      },
      //Add a single point marker
      addMarker(lnglat) {<!-- -->
        this.clearMap() //Clear the overlay

        //Custom mark point icon
        let markerObj = {<!-- -->
          icon: new T.Icon({<!-- -->
            iconUrl: 'http://api.tianditu.gov.cn/img/map/markerA.png',
            iconSize: new T.Point(30, 40),
            iconAnchor: new T.Point(15, 40),
          }),
        }
        this.mapConfig.marker = new T.Marker(
          this.returnLnglat(lnglat)
          // markerObj
        )

        //Add mark point right-click event
        this.mapConfig.marker.addEventListener('contextmenu', (event) => {<!-- -->
          console.log('Add mark point right-click event', event)
          //to do something
        })

        this.mapConfig.map.addOverLay(this.mapConfig.marker)
        this.reset('marker') //Adaptive screen

        //Add click event to point mark and pass parameters
        this.addClickHandler(this.mapConfig.marker, {<!-- -->
          lnglat: lnglat,
        })
      },
      //Add click event return
      addClickHandler(marker, params, index) {<!-- -->
        marker.addEventListener('click', (e) => {<!-- -->
          this.mapConfig.map.panTo(this.returnLnglat(e.lnglat), 12) //Transform the center point of the map to the specified geographical coordinates
          this.markerClick(e, params, index)
        })
      },
      // Click on the time to open the information form
      markerClick(e, params, index) {<!-- -->
        console.log(e, params, index)
        this.showInfoWindow = true //Show information window
        this.mapConfig.infoWindowData = params //Pass data

        //Create information window object
        this.mapConfig.infoWindow = new T.InfoWindow(
          this.$refs['infoWindow'].$el,
          {<!-- --> offset: new T.Point(0, -20), closeButton: false }
        )

        setTimeout(() => {<!-- -->
          this.mapConfig.map.openInfoWindow(this.mapConfig.infoWindow, e.lnglat) //Open the information window
        }, 0)
      },
      // Information window click callback
      infoWindowCallback(data) {<!-- -->
        console.log('Information window click callback', data)
        //to do something
        this.closeInfoWindow() // Close the information pop-up window
      },
      //Close the information pop-up window
      closeInfoWindow() {<!-- -->
        if (this.mapConfig.infoWindow) {<!-- -->
          this.mapConfig.infoWindow.closeInfoWindow()
        }
      },

      //Add multiple point markers
      addMarkers(path) {<!-- -->
        this.clearMap() //Clear the overlay
        let tempMarkers = []
        path.forEach((element) => {<!-- -->
          let tempMarker = new T.Marker(this.returnLnglat(element))
          this.mapConfig.map.addOverLay(tempMarker)
          tempMarkers.push(tempMarker)
        })
        this.mapConfig.markers = tempMarkers
        this.reset('markers') //Adaptive screen
      },
      //Add point aggregation
      addMarkerCluster() {<!-- -->
        this.clearMap('markerCluster') //Clear the overlay
        let tempMarkerCluster = []
        for (var i = 0; i < 100; i + + ) {<!-- -->
          // Define the approximate latitude and longitude range of Zhejiang Province
          var minLng = 118.018 // Minimum longitude
          var maxLng = 123.7088 // Maximum longitude
          var minLat = 27.0973 // minimum latitude
          var maxLat = 31.0493 // Maximum latitude

          // Randomly generate longitude and latitude within Zhejiang Province
          var randomLng = Math.random() * (maxLng - minLng) + minLng
          var randomLat = Math.random() * (maxLat - minLat) + minLat

          var marker = new T.Marker(this.returnLnglat([randomLng, randomLat]), {<!-- -->
            title:i,
          })
          tempMarkerCluster.push(marker)
        }

        this.mapConfig.markerCluster = new T.MarkerClusterer(
          this.mapConfig.map,
          {<!-- --> markers: tempMarkerCluster }
        )

        this.reset('markerCluster') //Adaptive screen
      },
      //Add a single line
      addLine(path) {<!-- -->
        this.clearMap() //Clear the overlay
        const tempPath = []
        path.forEach((element) => {<!-- -->
          tempPath.push(this.returnLnglat(element))
        })
        this.mapConfig.line = new T.Polyline(tempPath)
        this.mapConfig.map.addOverLay(this.mapConfig.line)
        this.reset('line') //Adaptive screen
      },
      //Add a single polygon overlay
      addPolygon(path) {<!-- -->
        this.clearMap() //Clear the overlay
        const tempPath = []
        path.forEach((element) => {<!-- -->
          tempPath.push(this.returnLnglat(element))
        })
        this.mapConfig.polygon = new T.Polygon(tempPath)

        //Add right click event
        this.mapConfig.polygon.addEventListener('contextmenu', (event) => {<!-- -->
          this.addRightMenu(event)
        })

        this.mapConfig.map.addOverLay(this.mapConfig.polygon)
        this.reset('polygon') //Adaptive screen
      },
      //Create right-click menu
      addRightMenu(e) {<!-- -->
        console.log('addRightMenu', e)
        if (this.mapConfig.contextMenu) this.clearRightMenu() //Clear the right-click menu

        this.mapConfig.contextMenu = document.createElement('div')
        this.mapConfig.contextMenu.id = 'contextMenu'
        this.mapConfig.contextMenu.innerHTML = `<div class='menu-item' id='edit'>Edit</div>
         <div class='menu-item' id='del'>Delete</div>`

        //Set menu position
        this.mapConfig.contextMenu.style.left = e.layerPoint.x + 'px'
        this.mapConfig.contextMenu.style.top = e.layerPoint.y + 'px'

        this.mapConfig.map
          .getContainer()
          .appendChild(this.mapConfig.contextMenu) // Add the menu to the map container

        document.getElementById('edit').addEventListener('click', () => {<!-- -->
          console.log('edit')
          this.clearRightMenu() //Clear the right-click menu
        })
        document.getElementById('del').addEventListener('click', () => {<!-- -->
          console.log('Delete')
          this.clearRightMenu() //Clear the right-click menu
        })

        //Listen to the click event of the map and hide the right-click menu
        this.mapConfig.map.addEventListener('click', () => {<!-- -->
          this.clearRightMenu() //Clear the right-click menu
        })
      },
      //Clear the right-click menu
      clearRightMenu() {<!-- -->
        var contextMenu = document.querySelector('#contextMenu')
        if (contextMenu) {<!-- -->
          this.mapConfig.map.getContainer().removeChild(contextMenu)
        }
        this.mapConfig.contextMenu = null
      },

      //Layer switching
      changeLayer(type) {<!-- -->
        let layerType = null
        switch (type) {<!-- -->
          case 'BZ': //Standard
            layerType = window.TMAP_NORMAL_MAP
            break
          case 'WX': //satellite
            layerType = window.TMAP_SATELLITE_MAP
            break
          case 'WXLW': //Satellite road network
            layerType = window.TMAP_HYBRID_MAP
            break
          case 'DX': //terrain
            layerType = window.TMAP_TERRAIN_MAP
            break
          case 'DXLW': //Terrain road network
            layerType = window.TMAP_TERRAIN_HYBRID_MAP
            break
          default:
            break
        }
        this.mapConfig.map.setMapType(layerType)
      },
      // clear map
      clearMap(type) {<!-- -->
        switch (type) {<!-- -->
          case 'marker':
            if (this.mapConfig.marker) {<!-- -->
              this.mapConfig.map.removeOverLay(this.mapConfig.marker) //Remove the overlay to the map
              this.mapConfig.marker = null
            }

            break
          case 'line':
            if (this.mapConfig.line) {<!-- -->
              this.mapConfig.map.removeOverLay(this.mapConfig.line) //Remove the overlay to the map
              this.mapConfig.line = null
            }

            break

          case 'markers':
            if (this.mapConfig.markers) {<!-- -->
              this.mapConfig.markers.forEach((item) => {<!-- -->
                this.mapConfig.map.removeOverLay(item) //Remove the overlay to the map
              })
              this.mapConfig.markers = null
            }
            break
          case 'circleMarker':
            if (this.mapConfig.circleMarker) {<!-- -->
              this.mapConfig.map.removeOverLay(this.mapConfig.circleMarker)
              this.mapConfig.circleMarker = null
            }
            break

          default:
            this.mapConfig.map.clearOverLays()

            // Clear all convergence point markers
            if (this.mapConfig.markerCluster) {<!-- -->
              this.mapConfig.markerCluster.clearMarkers() //Remove the overlay to the map
              this.mapConfig.markerCluster = null
            }

            //Clear the information window
            if (this.mapConfig.infoWindow) {<!-- -->
              this.mapConfig.infoWindow.closeInfoWindow()
            }

            break
        }
      },
      // Adapt the mark cover to the appropriate range
      reset(drawType) {<!-- -->
        let mapData = ''
        switch (drawType) {<!-- -->
          case 'marker':
            mapData = [this.mapConfig.marker.getLngLat()]
            break
          case 'markers':
            let tempMakerArr = []
            this.mapConfig.markers.forEach((element) => {<!-- -->
              tempMakerArr.push(this.returnLnglat(element.or))
            })
            mapData = tempMakerArr
            break

          case 'markerCluster':
            // Get the longitude and latitude coordinates of all marker points
            var allLng = 0
            var allLat = 0
            const tempMarkerClusterArr = this.mapConfig.map.getOverlays()
            tempMarkerClusterArr.forEach((element) => {<!-- -->
              allLng + = element.or.lng
              allLat + = element.or.lat
            })

            // Calculate the latitude and longitude coordinates of the center point
            var centerLng = allLng / tempMarkerClusterArr.length
            var centerLat = allLat/tempMarkerClusterArr.length

            // There is an error in the simulation calculation here. Generally, a certain longitude, latitude and level are fixed.
            this.mapConfig.map.centerAndZoom(
              this.returnLnglat([centerLng, centerLat]),
              7
            )

            break

          case 'line':
            mapData = this.mapConfig.line.getLngLats()
            break
          case 'polygon':
            mapData = this.mapConfig.polygon.getLngLats()[0] //Get the covering lattice array
            break

          default:
            break
        }

        this.mapConfig.map.setViewport(mapData) //Adapt to the range
      },
      // Return the longitude and latitude object of the sky map
      returnLnglat(data) {<!-- -->
        let x,
          y = null
        switch (typeof data) {<!-- -->
          case 'string':
            let lnglat = data.split(',')
            x = lnglat[0]
            y = lnglat[1]
            break
          case 'object':
            if (data & amp; & amp; data.lng) {<!-- -->
              x = data.lng
              y = data.lat
            } else {<!-- -->
              x = data[0]
              y = data[1]
            }

            break

          default:
            break
        }
        return new T.LngLat(x, y)
      },
    },
  }
</script>
<style lang="scss" scoped>
  // toolbar
  .tool_container {<!-- -->
    padding: 20px;
    ._btn {<!-- -->
      border: none;
      border-radius: 3px;
      padding:8px 12px;
      font-size: 12px;
      line-height: 1;
      background-color: #1890ff;
      color: #fff;

       & amp;:not(:first-of-type) {<!-- -->
        margin-left: 15px;
      }
    }
  }
  .map_container {<!-- -->
    width: 1000px;
    height: 600px;
    margin: 30px auto;
    z-index: 0;
    // Remove the default logo text in the lower left corner ---- If ::v-deep doesn’t work, use /deep/
    ::v-deep .tdt-control-copyright {<!-- -->
      display: none !important;
      opacity: 0 !important;
    }

    //Customize the right-click menu
    ::v-deep #contextMenu {<!-- -->
      position: absolute;
      z-index: 400;
      background: #fff;
      border-radius: 2px;
      .menu-item {<!-- -->
        height: 35px;
        line-height: 35px;
        word-break: break-all;
        padding: 0 10px;
        font-size: 12px;
        min-width: 60px;
        text-align: center;
        white-space: nowrap;
         & amp;:hover {<!-- -->
          background-color: #f3f3ee;
        }
      }
    }
  }
</style>

InfoWindow file

<template>
  <div class="infowindowClass">
    <div class="windows_close" @click="close"></div>
    <div class="_head">Information window customization</div>
    <div class="_body">
      {<!-- -->{<!-- --> data }}
    </div>
    <div class="_foot">
      <el-button type="primary" @click="callback">OK</el-button>
    </div>
  </div>
</template>
<script>
  export default {<!-- -->
    props: {<!-- -->
      // Pass data object
      data: {<!-- -->
        type: Object,
        default: () => {<!-- -->},
      },
      //Information window object
      infoWindow: {<!-- -->
        type: Object,
        default: () => {<!-- -->},
      },
    },
    methods: {<!-- -->
      // closure
      close() {<!-- -->
        this.infoWindow.closeInfoWindow()
      },
      //Confirm callback
      callback() {<!-- -->
        this.$emit('callback', this.data)
      },
    },
  }
</script>

<style lang="scss">
  // $color: red;
  $color: rgba(255, 255, 255, 1);

  // Information window hides source code style
  .tdt-infowindow-content-wrapper,
  .tdt-infowindow-tiptdt-infowindow-content-wrapper {<!-- -->
    color: unset;
    background: transparent;
    box-shadow: unset;
  }
  .tdt-infowindow-content {<!-- -->
    margin: 0;
  }

  .tdt-infowindow-tip-container {<!-- -->
    display: none;
  }

  // Information window hides source code style - end
  .infowindowClass {<!-- -->
    position: relative;
    // position: absolute;
    // top: 0;
    // left: 0;
    display: flex;
    flex-direction: column;
    width: 300px;
    height: 150px;
    padding: 10px;
    background-color: $color;
    border-radius: 10px;
    // zhtips: triangle
     & amp;::before {<!-- -->
      position: absolute;
      bottom: -9px;
      left: 50%;
      width: 0;
      height: 0;
      content: '';
      border-color: $color transparent transparent transparent;
      border-style: solid;
      border-width: 10px 10px 0 10px;
      transform: translate(-50%, 0);
    }

    ._head {<!-- -->
      padding-bottom: 10px;
    }
    ._body {<!-- -->
      flex: 1;
    }
    ._foot {<!-- -->
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }

  //zhtips: Close button X in the upper right corner of the window
  $closeColor: #333;
  .windows_close {<!-- -->
    position: absolute;
    top: 0;
    right: 0;
    width: 30px;
    height: 30px;
    transform: rotate(45deg);
     & amp;::before {<!-- -->
      position: absolute;
      top: 50%;
      left: 50%;
      display: block;
      width: 10px;
      height: 1px;
      content: '';
      background-color: $closeColor;
      transform: translate3d(-50%, -50%, 0);
    }

     & amp;::after {<!-- -->
      position: absolute;
      top: 50%;
      left: 50%;
      display: block;
      width: 1px;
      height: 10px;
      content: '';
      background-color: $closeColor;
      transform: translate3d(-50%, -50%, 0);
    }
  }
</style>

refer to
Tianditu Example: http://lbs.tianditu.gov.cn/api/js4.0/examples.html
Tianditu API: http://lbs.tianditu.gov.cn/api/js4.0/class.html