This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

Introduction to the

  • When developing large screen projects, there are tens of thousands of points on the map at a time. For the sake of page performance, we cannot draw tens of thousands of annotations to display.
  • There are two ways to do this:
  1. Overlay the top of the map with a canvas. Draw points on this canvas based on geographic coordinates and pixel transitions. All control is to be judged.
  2. Through baidu map coverage functionOverlay, the realization of custom canvas covering, painting point in the canvas covering. Map zoom in, zoom out, shift, the callback is controlled by the map.
  • Here’s the second way to do it.

mulch

  • All throughmap.addOverlay(), the content added to the map is overlay. Such as annotation, vector graphics element information window, etc. Coverings have their own geographic coordinates, and when you drag or scale the map, they move accordingly.
  • They all inherit fromOverlay, the abstract base class of the covering. This class cannot be instantiated.

Custom coverings

  • inheritanceOverlay, through the base class to implement custom covering functions.
  1. initialize(), which is used to initialize the overlay when calledmap.addOverlayWhen,APIThis method is called.
  2. draw()When the state of the map changes, the system calls to draw the overlay.
  3. show(), showing the cover.
  4. hide()To hide the coverings.
  • By instantiatingnew BMapGL.Overlay(). Modified the initialization methodinitializeAdd and return the canvas. Modify thedrawFunction to confirm the position and size of the canvas, convert point coordinates to pixel coordinates, and draw points at corresponding positions. At last,map.addOverlay()Put in the map.
      / * * *@param Map Map example *@param PTS Multiple point coordinates * */
      function customlayer(map, pts) {
        / / baidu
        var layer = new BMapGL.Overlay()
        layer.initialize = function () {
          this._map = map
          // Create the canvas element and add it to the layer container
          let cvs = document.createElement('canvas')
          // onMapClick(cvs)
          // getPanes() returns the list of map coverings
          // markerPane Annotates the container where the icon resides -- add the canvas
          map.getPanes().markerPane.appendChild(cvs)
          // Get the canvas object
          this._cvs = cvs
          return cvs
        }
        layer.draw = function () {
          // Set the appropriate position for SVG/Canvas
          // getSize() returns the size of the map view in pixels
          let size = this._map.getSize()
          // Return the longitude and latitude of the current center of the map
          let center = this._map.getCenter()

          // Get the center point of the map relative to the layer
          // pointToOverlayPixel() gets the coordinates of the corresponding covering container based on the geographic coordinates
          let rel_xy = this._map.pointToOverlayPixel(center)
          // Get the absolute position of the center of the map
          PointToPixel () converts the latitude and longitude coordinates to pixel coordinates
          let abs_xy = this._map.pointToPixel(center)

          // The difference between the two positions is the position of the canvas
          let left = rel_xy.x - abs_xy.x
          let top = rel_xy.y - abs_xy.y
          // Set the canvas position on the map
          this._cvs.setAttribute('style'.'position:absolute; left:' + left + 'px; top:' + top + 'px; z-index:1')
          // Set the canvas size to the map size
          this._cvs.setAttribute('width', size.width)
          this._cvs.setAttribute('height', size.height)

          // draw(map, pts, this._cvs)
        }
        map.addOverlay(layer)
      }
Copy the code

Plot points

  • At this point, we just need to convert the geographic coordinates of the points to pixel coordinates and draw them onto the canvas.
  • Of course, in order to make the function more powerful, here we add the judgment of the distance between points when obtaining the point coordinates, and combine the points within the distance into an aggregate point and draw. Determine and draw different point styles based on the aggregate number.
      / * * *@param Map Map example *@param POTS multi-point coordinates *@param Map Map instance * */
      function draw(map, pots, canvas) {
        const arr = [] // After the assembly point

        // Canvas creates the environment for drawing
        let ctx = canvas.getContext('2d')
        // Clear the canvas
        ctx.clearRect(0.0, canvas.width, canvas.height)

        // Aggregate distance
        let distance = 20
        // Return the geographical area of the cover
        let bound = map.getBounds()
        if (bound.ne.lng < 0) {
          bound.ne.lng = Math.abs(bound.ne.lng)
        }

        // Point aggregation calculation
        pots.forEach((spot) = > {
          // Check whether the point is within the map display area
          // containsPoint() : returns true if the point's geographic coordinates are inside the rectangle
          if (bound.containsPoint(spot)) {
            // Iterate over the set of points, comparing them to the elements in the aggregate array.
            If not, add an item to the aggregation array and record the number of points aggregated
            let position = map.pointToPixel(spot)
            if (arr.length == 0) {
              arr.push({ count: 1.pos: position })
            } else {
              // Determine whether the point is within the aggregation scope
              let flag = true
              for (let i = 0; i < arr.length; i++) {
                let c = arr[i]
                let pos = c.pos
                if (Math.abs(pos.x - position.x) <= distance && 
                Math.abs(pos.y - position.y) <= distance) {
                  c.count++
                  flag = false
                  break}}if (flag) {
                arr.push({ count: 1.pos: position })
              }
            }
          }
        })

        // Iterate over the aggregated data and render it on the canvas
        // The count value is a single point or an aggregate point
        arr.forEach((item) = > {
          let position = item.pos
          if (item.count == 1) {
            ctx.beginPath()
            ctx.fillStyle = 'rgba (102, 0, 204, 0.6)'
            ctx.strokeStyle = 'rgba (102, 0, 204, 0.6)'
            ctx.lineWidth = 2
            ctx.arc(position.x, position.y, 5.0.2 * Math.PI)
            ctx.closePath()
            ctx.stroke()
            ctx.fill()
          } else {
            ctx.globalAlpha = 0.6
            ctx.beginPath()
            ctx.fillStyle = '#87CEFA'
            ctx.ellipse(position.x, position.y, 20.10.0.0.2 * Math.PI, true)
            ctx.closePath()
            ctx.fill()
            ctx.globalAlpha = 1
            ctx.fillStyle = 'red'
            ctx.font = 'bold 17px Arial'
            ctx.fillText(item.count, 
            position.x - ctx.measureText(item.count).width / 2, position.y + 6)}}}Copy the code
  • Every time the map is changed, it’s calleddraw. In order to make the map more smooth, here add the map listener event, when the event started, stop drawing, and empty the canvas, after the end of the event, in the redraw.
function customlayer(map, pts) {
    let temEvent = false
    // Monitor baidu Map zoom event
    map.addEventListener('zoomstart'.function (e) {
      temEvent = true
    })
    map.addEventListener('zoomend'.function (e) {
      temEvent = false})... layer.draw =function () {
          if (temEvent) {
            let ctx = this._cvs.getContext('2d')
            ctx.clearRect(0.0.this._cvs.width, this._cvs.height)
            return}... }... }Copy the code
  • Testing capabilities
var pts = []
for (var i = 0; i < 1000; i++) {
    pts.push(new BMapGL.Point(Math.random() * 10 + 115.Math.random() * 10 + 25))
}
customlayer(map, pts)
Copy the code

  • This is just a brief introduction to using canvas to draw massive points on a map.
  • Interested parties can continue to improve this feature, such as adding a click event or a mouse move event for each point. Add external functions to modify point styles and so on.