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.