跪拜 Guibai
← All articles
Frontend · Vue.js

A TMap Utility for AMap in Vue 3: Markers, Areas, Loca Pulse Lines, and Vue-Powered InfoWindows

By 啾咪orJIUMI ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

AMap projects get a cleaner way to manage overlays and InfoWindows without leaving Vue's reactivity model. The pre-rendered DOM approach keeps the Vue context intact, avoiding the common pain of re-creating component instances inside map popups.

Summary

A Vue 3 + TypeScript utility class named TMap wraps the AMap JS API 2.0 and Loca 2.0 into a single set of methods. It covers map initialization, style and center control, markers (single, batch, drag, icon changes), polygons (render, draw, edit), polylines, Loca pulse line layers, point clustering, administrative district masks, and InfoWindows. The wrapper converts business data structures into AMap and GeoJSON formats internally, so page code only passes plain objects and callbacks.

The most notable part is how InfoWindows interact with Vue. The recommended path is to render a Vue component in the parent template, take its DOM element, and hand that to AMap.InfoWindow. Since Vue still owns the component, reactivity, Pinia, Router, and styles work normally. An alternative dynamic path uses createApp to mount a new component at runtime, but that requires installing plugins and explicitly unmounting to avoid memory leaks. The article also shows how Loca's PulseLineLayer demands GeoJSON FeatureCollection input, and how the administrative district mask builds a polygon with an outer rectangle and holes.

Takeaways
— TMap exposes 19 methods covering map init, markers, polygons, polylines, Loca pulse layers, clustering, and InfoWindows.
— The wrapper loads AMap 2.0 and Loca 2.0 via @amap/amap-jsapi-loader with plugins for MouseTool, Geocoder, PolygonEditor, DistrictSearch, PolylineEditor, and MarkerCluster.
— Loca's PulseLineLayer requires GeoJSON FeatureCollection data; business route objects must be converted with a formatGeoData function.
— The administrative district mask uses AMap.DistrictSearch to get boundaries, then draws a polygon with an outer rectangle and the district boundary as holes.
— InfoWindow can take a Vue-rendered DOM element as content; the article recommends pre-rendering in the parent template to reuse the current Vue app context.
— Dynamically created Vue components for InfoWindow require createApp, mounting, and an explicit unmount() on close to prevent duplicate instances and memory leaks.
— Cluster data can be reset or appended using setClusterData with 'reset' or 'add' modes.
— Adding a new pulse line regenerates the full GeoJSON and replaces the entire layer, which is simple but not incremental.
Conclusions

Passing a template-rendered DOM node to AMap.InfoWindow sidesteps the biggest friction of mixing map SDKs with Vue: keeping reactive state and shared plugins alive inside a popup.

The pulse layer's whole-layer replacement on each new route is straightforward but wasteful; a more efficient design would update the GeoJSON source in place.

Loca layers operate on GeoJSON rather than AMap's native overlay objects, so any business data destined for a pulse layer must be converted upfront, which is a design decision worth planning for.

Concepts & terms
AMap JS API 2.0
The JavaScript API for AMap, China's popular mapping service. Version 2.0 introduces a modular loader and supports plugins like DistrictSearch and MarkerCluster.
Loca 2.0
AMap's visualization library for animated and data-driven layers. It works with GeoJSON sources and provides layers like PulseLineLayer for flowing line animations.
PulseLineLayer
A Loca layer that renders lines with an animated pulse effect, showing flow direction and speed. It requires a GeoJSON FeatureCollection as its data source.
GeoJSON FeatureCollection
A standard JSON structure for a collection of geographic features. Loca and many map tools use it as an interchange format, with each feature holding geometry and properties.
From the discussion
Featured comments
THEKILL

Is it open source?

啾咪orJIUMI

No, just sharing examples of functionality I've built.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗