echarty
echarty copied to clipboard
map with shapefile polylines or polygons
Proof of concept - Leaflet map with shapefile polylines. Idea from @Robinlovelace. We prefer Leaflet map as most versatile. Other options are 'bmap' and gmap, which are based on Baidu and Google and require an API key.
destfile <- tempfile('shape')
download.file('https://apa.ny.gov/gis/GisData/Boundaries/AdirondackParkBoundary2017.zip',
destfile, mode='wb', method='curl')
unzip(destfile, exdir='unzipped') # new unzipped folder under getwd()
# convert shape coords to lat/lng
library(rgdal)
ogr <- readOGR(dsn= 'unzipped', layer= 'AdirondackParkBoundary2017')
tmp <- sp::spTransform(ogr, sp::CRS("+init=epsg:4326"))
# convert lat/lng to ECharts format in dt
dt <- list()
for(i in 1:length(tmp@lines)) {
df <- as.data.frame(tmp@lines[[i]]@Lines[[1]]@coords) # Adirondack
coords <- list()
for(k in 1:nrow(df)) coords <- append(coords, list(as.numeric(df[k,])))
dt <- append(dt, list(list(name= paste0('L',i), coords= coords)))
}
library(echarty)
p <- ec.init(load= 'leaflet')
p$x$opts$leaflet <- list(
zoom= 8, roam= TRUE, center= unlist(dt[[1]]$coords[1]))
p$x$opts$series <- list(
list(type= 'lines', coordinateSystem= 'leaflet', polyline= TRUE,
lineStyle= list(width=3), color= 'red',
#progressiveThreshold= 500, progressive= 200,
data= dt
)
,list(type= 'lines', coordinateSystem= 'leaflet', polyline= TRUE,
lineStyle= list(width=0), color= 'blue', zlevel= 1,
data= dt,
effect= list(show= TRUE, constantSpeed= 20, trailLength= 0.1, symbolSize= 3)
)
)
p$x$opts$tooltip <- list(show=TRUE)
p

If you like this solution, please consider granting a Github star ⭐ to echarty.
This looks good, many thanks @helgasoft! Do you have a working version starting with an sf object? sf supersedes sp so support for it would make this solution much more future-proof. Good news: switch from sp to sf should be easy and I can provide pointers if you need them.
Here is one way of getting the data through sf.
library(sf)
fname <- system.file("shape/nc.shp", package="sf")
nc <- st_read(fname)
dats <- list()
for(i in 1:nrow(nc)) {
geom <- as.data.frame(nc$geometry[[i]][[1]][[1]])
coords <- list()
for(k in 1:nrow(geom))
coords <- append(coords, list(c(geom$V1[k], geom$V2[k])))
dats <- append(dats, list(list(name= nc$NAME[i], coords=coords)))
}
centr <- as.data.frame(nc$geometry[[1]][[1]][[1]])
library(echarty)
p <- ec.init(load='leaflet')
p$x$opts$series <- list(
list(type='lines', coordinateSystem='leaflet', polyline= TRUE,
lineStyle= list(width=3), color= 'red', name= 'counties',
data= dats
))
p$x$opts$tooltip <- list(show= TRUE)
p$x$opts$legend = list(show= TRUE)
p$x$opts$leaflet$center <- c(mean(centr[,1]), mean(centr[,2]))
p$x$opts$leaflet$zoom <- 6
p

Previous example is with polylines. This one - with filled polygons. Tooltips show each polygon's name which is a county name from the sf shape data.
library(sf)
fname <- system.file("shape/nc.shp", package="sf")
nc <- st_read(fname)
cntis <- list() # counties
for(i in 1:nrow(nc)) {
geom <- as.data.frame(nc$geometry[[i]][[1]][[1]])
coords <- list()
for(k in 1:nrow(geom))
coords <- append(coords, list(c(geom$V1[k], geom$V2[k])))
cntis <- append(cntis, list(list(
type= 'custom', coordinateSystem= 'leaflet',
name= nc$NAME[i], # county name for tooltip
renderItem= htmlwidgets::JS('riPolygon'),
itemStyle= list(opacity= 0.3),
tooltip= list(formatter= '{a}'),
data= coords)))
}
centr <- as.data.frame(nc$geometry[[1]][[1]][[1]])
library(echarty)
p <- ec.init(load= c('leaflet', 'custom'),
series= cntis,
tooltip= list(show= TRUE)
)
# update leaflet presets
p$x$opts$leaflet$center <- c(mean(centr[,1]), mean(centr[,2]))
p$x$opts$leaflet$zoom <- 6
p

Nice! Could there be a function to visualise it in a single command, e.g. ec.sf(nc)
Implemented in latest echarty v.1.5.6.02. Check new command ?ec.util. See also more code and demo clip.
library(sf); library(echarty)
fname <- system.file("shape/nc.shp", package="sf")
nc <- as.data.frame(st_read(fname))
ec.init(load= c('leaflet', 'custom'), # always load custom for polygons
js= ec.util(cmd='sf.bbox', bbox=st_bbox(nc$geometry)),
series= ec.util(df= nc, nid= 'NAME', itemStyle= list(opacity= 0.3), verbose=TRUE),
tooltip= list(formatter= '{a}')
)
# scatter points can have a common name set for legend, no need for _nid_ param
fn <- ec.util(cmd= 'sf.unzip',
url= 'https://mapcruzin.com/sierra-leone-shapefiles/points.zip')
nc <- as.data.frame(st_read(fn))
ec.init(load= c('leaflet'),
js= ec.util(cmd= 'sf.bbox', bbox= st_bbox(nc$geometry)),
series= ec.util(df= nc, name= 'spots', itemStyle= list(color= 'red'), verbose=TRUE),
tooltip= list(formatter= '{a}'), legend= list(show= TRUE)
)
leaflet with timeline, for @leovan
tmp <- '
lng,lat,name,date,place
-118.808101,32.843715,"Seabed","2021-02-02","location A"
-117.332678,34.845565,"Lancaster","2021-04-02","location A"
-116.127504,32.846118,"fwy #8","2021-04-02","place B"
-117.316886,30.961700,"Baja","2021-07-02","place B"'
df <- read.csv(text= tmp, header= TRUE)
library(echarty)
df |> dplyr::group_by(place) |> ec.init(
load= 'leaflet',
leaflet= list(layerControl= list(position= 'topright'),
tiles= list(
list(
label= 'Open Street Map',
urlTemplate= 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
options= list(attribution= '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, Tiles courtesy of <a href="http://hot.openstreetmap.org/" target="_blank">Humanitarian OpenStreetMap Team</a>')
),
list(
label= 'Stamen',
urlTemplate= 'https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}{r}.{ext}',
options= list(attribution= 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>',
subdomains= 'abcd', maxZoom= 18, ext= 'png')
)
)
),
tl.series= list(type= 'scatter', coordinateSystem= 'leaflet',
symbolSize= 15,
encode= list(lng= 'lng', lat= 'lat', tooltip= c(3,4))),
tooltip= list(show= T), color= 'red'
)
if you like this solution, please consider granting a Github star ⭐ to echarty.