The coverings on the map

There are two ways to add coverings on the map. One is to render on canvas. For example, JSAPI GL draws MultiMarker/MultiPolygon and other vector graphics coverings, which are directly drawn on the upper layer of the base map by writing corresponding graphics data analysis and rendering programs. In this rendering mode, 3D deformation can also be realized when the Angle of view changes. Another way is to superimpose other DOM elements on the map container through CSS layout. In this way, DOM elements need to recalculated layout when the perspective changes, such as Marker/Polygon overlay of JSAPI V2 and InfoWindow information window of JSAPI GL. These are DOM coverings.

If you need to overlay a custom complex element, the first way is to implement the corresponding data parsing and shader program, need to understand the principles of WebGL rendering, costly and not flexible. The DOM is familiar to every front-end engineer, and a few tags and CSS can create highly customized DOM elements. But how do you place a DOM element correctly on a map and adjust its position in real time as the map pans, rotates, and zooms?

So this is going to use the DOMOverlay. It is not a concrete DOM overlay, but an abstract base class for all DOM overlay, from which InfoWindow inherits. DOMOverlay abstracts the life cycle, common attributes, and methods of the DOM overlay. It allows you to monitor the binding and unbinding of map events. You only need to focus on the DOM node creation and location calculation methods.

DOMOverlay Interface design

DOMOverlay is an example of the DOMOverlay class. It uses the Donut class as an implementation of DOMOverlay.

Public properties and methods

Event listening and triggering

From the picture above shows, DOMOverlay inherited from the Node. Js EventEmitter class, so it has achieved event listeners, trigger, and other functions of encapsulation, not familiar with classmates can take a look at the Node. Js EventEmitter | novice tutorial.

Map binding and unbinding

DOMOverlay has a common attribute map whose value is the map instance of the overlay binding, and provides setMap(map: map) and getMap() methods as accessors to the map parameters. To display a custom overlay on a map, you first need to specify the specific map instance. There are two ways: first, define the map attribute in the initialization parameter, and second, set it dynamically through setMap, which can be bound to another map instance or unbound. What does setMap do? When binding, the DOM element returned by createDOM() is added to a specific node so that it can be overlaid and positioned relative to the map. The other is to perform updateDOM(), which listens for map transformations, so that DOM elements can follow the map to update location or content. Unbinding removes it from the parent node and removes the listener for the map event.

DOM elements

The common attribute dom of DOMOverlay refers to a specific element of the overlay. It can be HTMLElement or SVGElement. The element is created by subclasses and is attached to a div container on top of the canvas after the map is bound.

The destruction

When the coverings are no longer in use, they should be destroyed to prevent memory leaks. The destroy method encapsulates what should be done at the time of destruction, binding the earth diagram on the one hand and removing any listeners registered on the object on the other.

Abstract methods

DOMOverlay provides four abstract methods that are called at different stages of the life cycle.

  • onInitCalled during initialization with the constructor arguments passed throughoptionsFor parameter injection
  • createDOMCalled in the initialization phase, it is used to create and return a DOM element as the value of a DOM attribute to be appended to a specific parent node
  • updateDOMCalled when a map is panned, scaled, or rotated to update DOM element positioning
  • onDestroyCalled in the destruction phase, you can delete custom objects and event listeners in this function

The specific life cycle is as follows:

Based on theDOMOverlayImplement custom coverings

Take 🌰 : custom circular pie charts

Use Donut as an example to create a custom circular pie chart. The example on the official website uses native JS syntax to implement inheritance. Here we use ES6 syntax to implement inheritance:

const SVG_NS = 'http://www.w3.org/2000/svg'; DOMOverlay class Donut extends tmap. DOMOverlay {constructor(options) {super(options); } // Initialize: OnInit ({position, data, minRadius = 0, maxRadius = 50,} = {}) {object. assign(this, {position, data, minRadius, maxRadius, }); CreateDOM () {let SVG = document.createelementns (SVG_NS, 'SVG '); SVG. SetAttribute (' version 'and' 1.1 '); svg.setAttribute('baseProfile', 'full'); let r = this.maxRadius; svg.setAttribute('viewBox', [-r, -r, r * 2, r * 2].join(' ')); svg.setAttribute('width', r * 2); svg.setAttribute('height', r * 2); svg.style.cssText = 'position:absolute; top:0px; left:0px; '; let donut = createDonut(this.data, this.minRadius, this.maxRadius); svg.appendChild(donut); return svg; } // Update the DOM element with updateDOM() {if (! this.map) { return; } / / latitude and longitude coordinates container pixel coordinates the let pixel = this. Map. ProjectToContainer (enclosing the position). // let left = pixel.getx () - this.dom.clientWidth / 2 + 'px'; let top = pixel.getY() - this.dom.clientHeight / 2 + 'px'; this.dom.style.transform = `translate(${left}, ${top})`; OnDestroy () {}}Copy the code

Where createDonut creates the corresponding SVG graph based on the data and radius, we will not pay much attention here.

How do I locate elements?

Here we focus on the implementation of updateDOM and how to perform location updates. First, we assign a value to position during initialization. Position is a latitude and longitude object that can be converted to the pixel coordinates in the map container through the map.projectToContainer method, denoted as Pixel. The map container coordinate system is a coordinate system with the top left corner of the map container as the origin, positive x direction to the right and positive Y direction to the bottom. In addition, in the createDOM method we set the CSS position: Absolute; top:0px; left:0px; So the element is actually positioned to align with the top left corner of the map container. We need to align the center of the circular pie chart with the pixel position. First, we can obtain the width and height of the element through clientWidth/clientHeight, then calculate the pixel coordinates of the upper left corner of the element as (left, top), and finally transform: Translate (${left}, ${top}) sets the translation offset to move the element to the corresponding position.

${top}; Left: ${left} Because transform performs much better than top/ Left. Top /left is calculated on the CPU, causing the surrounding area to be redrawn; The transform takes advantage of GPU computing power and transforms in an independent layer without causing redrawing. See why Translate () is better than Top/Right /bottom/ Left when creating a front translation animation.

How to implement click listening?

Some students find that after creating a custom overlay, they can’t listen for click events through on(‘click’) like MultiMarker. Why? Joy: First, you need to listen for DOM elements to click on. This is done in createDOM:

CreateDOM () {// Create a DOM Element and return an Element. // DOMOverlay is derived from EventEmitter, which can emit events this.onclick ('click'); }; SVG. AddEventListener ('click', this.onclick); return svg; }Copy the code

You can use the click event callback to perform the action you want, or call the EMIT event to trigger the listener mounted via ON, as follows:

Let donut = new donut ({map, position: new tmap.latLNG (40.02906301748584, 116.25499991104516), data: [18, 41, 50], minRadius: 20, maxRadius: 28}) donut.on('click', () => {console.log(' ring graph is clicked, position is ${donut.position} '); });Copy the code

Note that the event listener should be removed at the time of destruction, so onDestroy should be modified accordingly:

/ / destruction to the unbundling event listeners onDestroy () {if (this. The onClick) {this. The dom. The removeEventListener (enclosing the onClick); }}Copy the code

Similarly, you can listen for mouseDown, Mouseup, touchStart, TouchEnd and other events on the mobile end. Since it’s a custom element, you have control.

Why the offset?

After some students implement custom coverings, they find that creating multiple elements will offset downward, and the offset becomes more and more one by one. Why? You might want to check that the DOM element is not set to position:absolute; top:0px; left:0px; If the absolute position is not set and the coordinate is (0, 0), the transform is offset from the original position of the element, and the element does not leave the document flow, and the added elements will move down in turn.

Other applications

DOMOverlay can be applied to a variety of graphe-text elements that are not easy to draw. For example, when using the point-aggregate interface, if you want to use a custom style and need to display the cluster size, you can use a custom DOM element to express the aggregate cluster.

For example, in the editor, graphics need to change in real time when drawing and editing graphics. Using vector graphics layers requires constant reconstruction of data, which has a large overhead. Therefore, it is also combined with DOM overlay to render single graphics in SVG.

In addition, some students also asked, how can marker jump animation in JSAPI V2 be realized in GL? In fact, custom coverings can also be used to achieve this. The official website also provides a marker animation example.

When is DOMOverlay not appropriate? Note that DOMOverlay is not appropriate when you need to draw a large number of overlays (>1000), because each DOM element is individually evaluated for location updates, which can be very expensive and slow when the map changes. It is still recommended to use MultiMarker/MultiPolygon and other vector graphics layers for rendering mass coverings, or the location data visualization API, which provides scatter map, arc map, track map, region map and other visualization types.

The following is reprinted from the article “JSAPI- Adding custom coverings to maps” by Lovato Learning

Dodoro loves to learn

Links: juejin. Cn/post / 684490…

Source: Nuggets

Copyright belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.