Introduction to the

As always, I would like to share with you an interesting requirement encountered in a project and describe how it was implemented.

Without further ado, get straight to the picture above:

In short, the specific application scenario requires us to add the custom overlay as shown in the figure on the map. The author is divided into the following two points to introduce the process.

  • Realization of water ripples
  • Implementation of custom coverings

Realization of water ripples

The realization of this requirement is certainly inseparable from our own writing custom overlay, so first let’s discuss the realization of a water ripple animation.

First of all, we can see that the covering in the picture is composed of a red heart and water ripples, where the red heart is fixed, so we can directly write:

  <div class="radar"></div>
Copy the code
  .radar {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      background-color: red;
  }
Copy the code

We can see that there are three ripples of water spreading from the inside out. If we look at it from a water ripple alone, in fact, the principle of outward diffusion is to make the width and height of the water ripple gradually increase to a certain extent through animation. How big is the specific diffusion? Readers can set the final width and height of the water ripple according to their own needs. The basic structure and style of water ripples are as follows:

  <div class="radar">
    <div class="ripple"></div>
    <div class="ripple"></div>
    <div class="ripple"></div>
  </div>
Copy the code
  .radar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: red;
    position: relative;
    .ripple {
      width: 40px;
      height: 40px;
      border-radius: 50%;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      border: 1px solid red;
      animation: ripple 2slinear infinite; }}Copy the code

The reason why the DOM nodes of water ripples are nested in the radar node is to create a “child separated from parent phase” positioning to achieve the effect of centering the water ripples. This should be easy to understand. As for the initial width and height of the water ripple, in order to facilitate the calculation of animation delay time, I set it to be equal to the width and height of the heart. If readers are interested, they can try to set the width and height to any value between 0 and 40px to see the effect. (The author may have a slight flaw in the animation, and may not ——> “Manual head”).

As for the realization of animation, it is very simple. We only need to gradually increase the width and height of the water ripple at the same time. However, it should be noted that the water ripple will disappear at last.

  @keyframes ripple {
    to {
      width: 150px;
      height: 150px;
      opacity: 0; }}Copy the code

At this point in the code, we have implemented the water ripple, but isn’t there something missing? What about the three ripples we talked about?

This problem is easy to solve, we just need to set the corresponding animation delay for the water ripple.

  .radar :nth-child(1) {
    animation-delay: 0.666 s;
  }
   .radar :nth-child(2) {
    animation-delay: 1.322 s;
  }
Copy the code

So now we have the ripples of water.

Implementation of custom coverings

This time the author uses the requirements of Baidu Map, so how to achieve custom coverage through Baidu Map?

In fact, Baidu map development documents are also very straightforward to show us custom coverage of the open box method. Here the author uses es6 class to rewrite the writing method slightly, the truth is the same, the official case can refer to Baidu map demo

Custom coverings are implemented in the following three steps:

  • Define the constructor and inherit the Overlay
  • Initialize custom coverings
  • Drawing overlay

Define the constructor and inherit the Overlay

According to the official website: “First you need to define the constructor for your custom overlay, with the constructor argument passing some free variables. Set the prototype property of the custom Overlay object to an instance of the Overlay to inherit the Overlay base class.

Using ES6 class we can quickly achieve:

Point transfers the coordinate position, which is used to calculate the position of the covering on the map.

class RadarOverlay extends BMap.Overlay	{
  constructor(point) {
    super(a);this.point = point; }}Copy the code

Initialize custom coverings

The official line is: “Implement the Initialize method, which is called by the API when the map.addOverlay method is called. When the map.addOverlay method is called to add a custom overlay, the API calls the initialize method of the object to initialize the overlay. During initialization, the DOM elements needed to create the overlay are added to the map container. Here we choose to add to the container markerPane.”

The initialize method is used to initialize the overLay. The initialize method creates the REQUIRED DOM during initialization. So we implement an Initialize in our own constructor (here we are using a class).

Baidu map official website method:

So we define an Initialize method in our class as required by the official website. Template stores the DOM element we need for initialization. The DOM node here will have a parent node whose className is Rader-box compared with the link above to realize water ripple. As you can see in the official DOM instance, position: Absolute is added to the DOM node. However, since the position of our radar node is relative, we need to nest more DOM nodes in the outermost layer to ensure that the whole DOM is positioned relative to the map. The parent’s position is absolute.

  initialize(map) {
    this._map = map;
    const template = `
      
`
; // Create a document fragment const divFragment = document.createRange().createContextualFragment(template); const div = divFragment.querySelectorAll('.radar-box') [0]; // Add div to the wrapper container map.getPanes().markerPane.appendChild(div); this._div = div; return div; } Copy the code

In this way, we have successfully defined an initialize method in our class. We can explain why we want to add divs to our coverings.

Baidu Map has provided us with a number of methods to display coverings. Our customized coverings are actually saved under one of the coverings we choose. Interested partners can go to know about various coverings containers.

Drawing overlay

So far, we’ve only added the overlay to the map, but we haven’t put it in the right place. You need to set the position of the overlay in the DRAW method, which is called by the API whenever the state of the map changes (e.g. position shift, level change) and is used to recalculate the position of the overlay. The map.pointtooverLayPixel method converts geographic coordinates to the required pixel coordinates of the overlay.”

The draw method in the overlay is called again after the map is scaled, which is used to re-calculate the location of the overlay.

So where does the draw method come from?

So the official meaning is that we define a draw method in the constructor of the custom overlay, in which we use baidu map’s map.pointtooverLayPixel method (used to convert geographic coordinates to pixel coordinates) to convert the geographic coordinates to the required pixel coordinates of the overlay.

All we need to do is add the draw method to the class: This. point is the point coordinate point in our constructor, and 40 represents the initial width and height of the entire water ripple. Readers can actually change 40 to a form that can be passed, such as this.size, which will facilitate the maintenance of the subsequent code.

  draw() {
    // Convert to pixel coordinates based on geographic coordinates and set to container
    const position = this._map.pointToOverlayPixel(this.point);
    this._div.style.left = `${position.x - 40 / 2}px`;
    this._div.style.top = `${position.y - 40 / 2}px`;
  }
Copy the code

At this point, our entire custom overlay class has been implemented, the overall code diagram (here to change 40 to this.size code is slightly easier to maintain) :

class RadarOverlay extends BMap.Overlay {
  constructor(point, size) {
    super(a);this.point = point;
    this.size = size;
  }

  initialize(map) {
    this._map = map;
    const template = `
      
`
; const divFragment = document.createRange().createContextualFragment(template); const div = divFragment.querySelectorAll('.radar-box') [0]; map.getPanes().markerPane.appendChild(div); this._div = div; return div; } draw() { // Convert to pixel coordinates based on geographic coordinates and set to container const position = this._map.pointToOverlayPixel(this.point); this._div.style.left = `${position.x - this.size / 2}px`; this._div.style.top = `${position.y - this.size / 2}px`; }}Copy the code

Use of custom coverings

Now that we’ve implemented custom coverings, the first thing to do is to put them to use, as follows:

    initMap() {
      const map = new BMap.Map(this.$refs.map);
      map.centerAndZoom(new BMap.Point(116.404.39.915), 15);
      We want to draw the point coordinates of the custom overlay
      const point = new BMap.Point(116.404.39.915);     
	// Instantiate the custom overlay, passing the coordinates and dimensions of the water ripples into the constructor
      const radar = new RadarOverlay(point, 40);    
      // Add custom overlay
      map.addOverlay(radar);
    }
Copy the code

The effect is as follows:

conclusion

As for the construction of a custom overlay of other content, big guys if you want to go into the baidu map can refer to the document, which must be more detailed than the author (dog). If the content of the article has a problem, welcome to leave a message, I hope to communicate with all the leaders, if you like the author’s article, don’t forget to give me a thumbs-up, this is very important to me.

Source address: https://gitee.com/zhao_jiahao/baidu-map-custom-cover