Welcoming JavaScript library AMap into the world of R.
AMap is an advanced mapping library made in China and widely used there.
It features 2D/3D animation, supports a multitude of layers and markers,
data import, flyover playback, etc.
Library amapro let you
control AMap from R and Shiny. It uses AMap’s native commands/parameters
wrapped in just a few commands.
Translation
AMap’s documentation is in Chinese and most links here make reference to it. If you happen not to know Chinese, it is convenient to set your browser to auto-translate. This will help a little or a lot depending on the website/page structure. One can also copy/paste text to Google translate.
Installation
Install amapro from Github withremotes::install_github("helgasoft/amapro")
CRAN version also available but usually outdated.
Run with the following commands library(amapro); am.init()
A pop-up dialog will ask
for an API key (shows once, will not be repeated).
API key is obtained through registration, expecting
you to provide a Chinese phone number for SMS verification.
How to
get an API key if you reside out of China?
- ask a friend from China to help, or hire a local freelancer
- search the web for a shared key
- use a temporary Chinese phone number from sites like sms24.me, turtle-sms.xyz, etc. However most are probably blacklisted as the registration page shows them as ‘already registered’.
- select temporarily the ‘demo’ option, without guarantee to work in the long run
Shiny Demo
Interactive, hands-on showcase of many library features. Activate
with the following command: library(amapro); demo(am.shiny)
API links
amapro is based on version 2.0 of AMap (JSAPI v2.0). “API” auto-translates as “Reference book” in web menus.
Commands
Controlling map and elements is done by sending AMap commands to
them. Commands can be chained with the pipe operator |> or %>% and
are executed sequentially in the order received.
Example:
am.cmd('setAngle', 'carIcon', -90)
amapro
uses native AMap commands and introduces these
additional:
-
set - create new element
- with name: add new global JS object outside the map
am.cmd('set', 'VectorLayer', name='e$layer1')
- without name: add new element to map
am.cmd('set', 'e$marker1', position= c(116.478, 39.998))
- with name: add new global JS object outside the map
-
addTo - append one existing JS object to another by
name
am.cmd('addTo', 'e$layer1', 'e$marker1')
-
var - set a JavaScript variable
am.cmd('var', 'e$myOpacity', 0.8)
-
code - execute JavaScript code
am.cmd('code', 'alert("I am JS");')
AMap commands starting with get return data from the
map or related objects.
Put the data in a Shiny input variable by
setting its name in parameter r.
Example:
am.cmd('getCenter', 'map', r='inShiny1')
Above command
will update input$inShiny1 with the Lng/Lat coordinates of the
map center.
Events
Events could be defined for map and elements. All types of instances
use on/off methods to bind and remove events.
Events are set in attribute on(or off)
as a list of lists. Each event is a separate list with event name in
e, a JS function f and optionally a
query q.
Example:
am.init(center= c(116.475, 39.997), zoom= 17,
on= list(list(e= 'complete',
f= "function() {alert('loaded!');}")) )
on/off events without name are ignored, except for the map
itself (as above example).
JavaScript function
Shiny.setInputValue() can be used to send data back to
Shiny.
Limitations
- only one map is created by am.init per session. It is a JS global called ‘m$jmap’.
- AMap command addTo is overwritten by amapro and cannot be used.
- the supported AMap plugins are: ControlBar, Scale, ToolBar, MoveAnimation, MouseTool, HeatMap, GeoJSON, ElasticMarker.
- most built-in AMap tile layers (Satellite, Traffic, Roads) are limited to China only. However, with command am.item(‘TileLayer’), one can use any Leaflet provider for worldwide coverage.
- AMap built-in map layers are GCJ-02 coded and coordinates collected on them will display incorrectly in Leaflet or other WGS-84 based maps, and vice-versa. They need to be converted. Conversion is available through function convertFrom.
- AMap ecosystem is vast, unsupported features include: ‘BesizerCurve’, ‘MarkerCluster’, ‘HawkEye’, IndoorMap, CustomLayer, ‘GLCustomLayer’, ‘DistrictLayer’, ‘LayerGroup’, all editors like ‘PolygonEditor’,‘Webservice’, ‘Search(AMap.Autocomplete, AMap.PlaceSearch)’, ‘Geocoding(AMap.Geocoder)’, Route planning, other services(weather, districts, etc.), positioning, utilities.
- most Loca elements are supported, but not all have been tested. Latest AmbientLight, DirectionalLight and PointLight objects are not supported, but parameters ambLight, dirLight and pointLight accomplish the same. Loca events are not supported yet.
- loca.js file has several versions, the latest (bigger) one does not work well with the current amap.js
Tips
all named objects created in JS are global variables (window.name). Good practice is to use a name prefix (m$) to avoid overwriting accidentally external variables.
API attributes could be set to a JS function instead of a value. Function is defined as a string starting with word “function”.
usually WMS/WMTS tiles come from external servers and may present a CORS problem - browser refusal to load. One can install a small extension in Chrome or Firefox to fix this problem manually inside the browser.
AMap has several predefined Map styles. Could be set in map options with mapStyle.
amapro silent errors are collected in the browser Console. Press key F12 to open the dev.environment, then open tab “Console” to view them.
Chrome/Firefox extensions may interfere with map presentation (like ‘uBlock’)