Map search of Tencent location service point aggregation application

Effect of chain home

analysis

The map room finding function is realized by point aggregation. An example of the official website is as follows: https://lbs.qq.com/javascript_v2/sample/overlay-markercluster.html

The map of Lianjia is mainly divided into three floors. The first floor is the urban floor, such as Nanshan, Luohu, etc; The second floor is the area, such as Nantou, science and Technology Park, etc; The third floor is the community.

Because there is not so much data in the first and second layers, these two interfaces return all data to the front end at one time. However, the amount of data in the third layer is very huge. The chainer returns part of the data, transmits the maximum latitude and longitude and the minimum latitude and longitude displayed on the front-end page to the background, and then returns the filtered data to the front-end. (you can use Chrome's development tools to capture the interface address. It should be noted that the linker's interface is in the form of jsonp, so you need to capture JS)

realization

First of all, we need to add the API of Tencent map. Here we recommend using asynchronous loading. Because the project uses the single page application developed by Vue, it is possible that the user does not enter the map room finding page. Therefore, it is recommended to add the API of Tencent map when opening the map room finding page.

Asynchronous loading needs to avoid a problem of repeated loading, that is, no matter how many times the user opens the map to find a room, the API of the map is the same. In order to reduce the code complexity, the singleton mode is not used. The specific code is as follows:

const TXMap = {
  map: undefined, // Map instance
  // Asynchronous load acquisition api
  getApi (funName) {
    let script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = `http://map.qq.com/api/js?v=2.exp&callback=${funName}`
    document.body.appendChild(script)
  }
}

It can be seen that asynchronous loading is the dynamic addition of script tags. src is the address of Tencent map api. src contains a callback parameter, indicating that funName will be called after js is loaded. After adding the map api, the window object will have a QQ Maps object, which can be used to judge whether the api has been added to avoid adding the api repeatedly.

The next step is to implement the method of custom covering. Or refer to official documents: https://lbs.qq.com/javascript_v2/doc/overlay.html

const TXMap = {
  map: undefined,
  overlays: [], // Store all coverings
  sourceData: [], // raw data
  listener: undefined, // Event listener for map zooming or panning

  getApi () {}, /* It has been stated above and is omitted here */

  // Implement custom overlays
  drawOverlay (options) {
    let _this = this // Here are several methods of window objects to avoid the pointing problem of this
    this.sourceData = options.data // Store original data
    // Before drawing the cover, clean up the previously drawn cover
    this.clearOverlays()

    // If the initMap method has been implemented, we can call it directly, otherwise it needs to be defined
    if (window.initMap === undefined) {
      window.initMap = function () {} // Concrete implementation of drawing covering 

      // If the map api is not introduced, call the getApi method; otherwise, directly call initMap ()
      window.qq === undefined ? this.getApi('initMap') : window.initMap()
    } else {
      window.initMap()
    }
  },
  // Clear custom covers
  clearOverlays () {
    let overlay
    while (overlay = this.overlays.pop()) {
      overlay.onclick = null // Remove click event
      overlay.parentNode.removeChild(overlay) // Remove dom element
    }
  },
  // In the beforeDestroy call of Vue component, reset the map and remove the time for listening to avoid memory leakage
  clearMap () {
    this.map = undefined
    if (this.listener) {
      window.qq.maps.event.removeListener(this.listener)
    }
  }
}

The shelf for finding rooms on this map is almost set up here. Next, let's take a look at the specific implementation of drawing covers, that is, the initMap method.

window.initMap = function () {
  if (_this.map === undefined) {
    // When the map object is undefined, you need to draw the map
    _this.map = new window.qq.maps.Map(document.getElementById(options.containerId), {
      // Initialize map Center
      center: new window.qq.maps.LatLng(options.lat || 22.702, options.lng || 114.09),
      // Initialize zoom level
      zoom: options.zoom || 10,
      // Minimum zoom level of map
      minZoom: 10,
      // Disable zoom control
      zoomControl: false,
      // Deactivate map type control
      mapTypeControl: false
    })
    // idle event, which is triggered after zooming or panning the map
    _this.listener = window.qq.maps.event.addListener(_this.map, 'idle', () => {
      // Get the maximum and minimum latitude and longitude of the visual range of the current map
      let bounds = _this.map.getBounds()
      // Gets the zoom level of the current map
      let zoom = _this.map.getZoom()
      // Call the processing function of Vue component for idle event
      options.callback && options.callback(bounds, zoom)
    })
  }

  // Custom cover
  if (window.CustomOverlay === undefined) {
    window.CustomOverlay = function (lat, lng, name, houseCount) {
      // Call the map api to calculate the location of the cover
      this.position = new window.qq.maps.LatLng(lat, lng)
      this.name = name // Area name
      this.houseCount = houseCount // Number of houses
    }
    // Inherit Overlay
    window.CustomOverlay.prototype = new window.qq.maps.Overlay()
    // Customize the cover constructor to define the DOM structure, DOM structure and style of the cover. You can draw it yourself according to your needs
    window.CustomOverlay.prototype.construct = function () {
      let div = this.div = document.createElement('div')
      div.className = 'my-overlay' // Cover class name
      // Covering html structure
      this.div.innerHTML = `<p class="count" >${this.houseCount}<span>set</span></p><p class="name">${this.name}</p>`
      //Add dom to the covering layer and overlay mousetarget's sequential container 5. This container contains transparent mouse corresponding elements, which are used to receive the mouse events of the Marker
      this.getPanes().overlayMouseTarget.appendChild(div)
      // Add div to overlays, which can be processed later
      _this.overlays.push(div)
      // Define the click event of the cover
      let center = this.position
      this.div.onclick = function () {
        // Click to zoom and pan the map
        let zoom = _this.map.getZoom()
        if (zoom < 13) {
          _this.map.setCenter(center)
          _this.map.setZoom(13)
        } else if (zoom >= 13 && zoom < 15) {
          _this.map.setCenter(center)
          _this.map.setZoom(15)
        }
      }
    }

    // Implement the draw interface to draw DOM elements
    window.CustomOverlay.prototype.draw = function () {
      let overlayProjection = this.getProjection()
      // Gets the relative pixel coordinates of the cover container
      let pixel = overlayProjection.fromLatLngToDivPixel(this.position)
      let divStyle = this.div.style
      // Adjust the position of positioning according to DOM elements
      divStyle.top = pixel.y - 53 + 'px'
      divStyle.left = pixel.x - 30 + 'px'
    }
  }

  // Draw the covering according to the interface data
  if (_this.sourceData.length > 0) {
    _this.sourceData.map(item => {
      let customOverlay = new window.CustomOverlay(item.latitude, item.longitude, item.name, item.house_count)
      customOverlay.setMap(_this.map)
    })
  }
}

So far, the mapping room has completed the encapsulation of the covering drawing method. Next, you only need to expose the TXMap, introduce it into the Vue component, and then use it to the following methods

TXMap.drawOverlay({
  containerId: 'map-box',
  data: res.data
})

Realization effect

This example uses the data of chain home to make two layers. You can modify it according to your own needs.

Project address: GitHub

Product dynamics

Tencent location service has launched 3D map API- JavaScript API GL.

Link to 3D map API document corresponding to the above functions: Point aggregation,Custom cover

The above content is reproduced from the front-end develop ep article "Tencent map realizes map room finding function"

Author: front end develop er

Link: https://juejin.im/post/6844903510614474759#comment

Source: Nuggets

The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Tags: Javascript Vue.js lbs prototype

Posted by welsh_sponger on Mon, 23 May 2022 08:01:57 +0300