Skip to content

Commit bfd9889

Browse files
committed
v.0.1.1
1 parent d7f7cfd commit bfd9889

18 files changed

+437
-153
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ vignettes
1717
README.md
1818
^CODE_OF_CONDUCT\.md$
1919
^README\.Rmd$
20+
^man/figs$

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ inst/doc
66
.V8history
77
.vscode
88
.DS_Store
9+
.Rbuildignore
10+
CRAN-RELEASE

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: echarty
22
Title: Minimal R/Shiny Interface to Library 'Echarts JavaScript'
3-
Date: 2021-01-29
4-
Version: 0.1.0
3+
Date: 2021-02-20
4+
Version: 0.1.1
55
Authors@R: c(
66
person("Larry", "Helgason", email = "larry@helgasoft.com", role = c("aut", "cre", "cph")),
77
person("John", "Coene", email = "jcoenep@gmail.com", role = c("aut", "cph"))

LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ Apache License
175175

176176
END OF TERMS AND CONDITIONS
177177

178+
Original work Copyright 2014 Taiyun Wei, Yihui Xie, Yang Zhou
178179

179180
Original work Copyright 2018 John Coene
180181

NAMESPACE

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
# Generated by roxygen2: do not edit by hand
22

33
export("%>%")
4+
export(ec.band)
45
export(ec.data)
56
export(ec.examples)
67
export(ec.fromJson)
78
export(ec.global)
89
export(ec.init)
910
export(ec.inspect)
10-
export(ec.sband)
11+
export(ec.js2r)
12+
export(ec.plugjs)
1113
export(ec.theme)
1214
export(ecs.exec)
1315
export(ecs.output)
1416
export(ecs.proxy)
1517
export(ecs.render)
1618
import(htmlwidgets)
1719
importFrom(magrittr,"%>%")
20+
importFrom(utils,askYesNo)
21+
importFrom(utils,download.file)

NEWS.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
# log history of echarty package development
22

3-
## echarty v0.1.0
4-
* initial release Feb 2021
3+
## echarty 0.1.1
4+
5+
- added ec.plugjs - install unknown plugins, like JS maps
6+
- added ec.js2r - a JS to R translation assistant, a Shiny app
7+
- ec.init update: one-time install for all plugins except built-in leaflet/custom
8+
- GL merged with 3D as plugin '3D'
9+
- more plugins: liquidfill, world, wordcloud, gmodularity
10+
- ec.sband renamed to ec.band
11+
12+
## echarty 0.1.0
13+
- initial release, approved by CRAN Feb 16, 2021

R/echarty.R

Lines changed: 136 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@
44
#'
55
#' Initialize a chart.
66
#'
7-
#' @param df A data.frame to be used as dataset in the chart, default NULL
8-
#' @param load Name(s) of plugin(s) to load. Currently supported are
9-
#' \emph{3D, GL, leaflet, custom}. Could be a vector or comma-delimited string. default NULL.
10-
#' @param preset Enable (TRUE, default) or disable(FALSE) presets like xAxis,yAxis,dataset,series, but not \code{group1}.
11-
#' @param group1 Preset parameters if df is grouped, default TRUE \cr
7+
#' @param df A data.frame to be preset as \href{https://echarts.apache.org/en/option.html#dataset}{dataset}, default NULL
8+
#' @param group1 Type of grouped series, default 'scatter'. Set to NULL to disable. \cr
129
#' If the grouping is on multiple columns, only the first one is used.
10+
#' @param preset Enable (TRUE, default) or disable(FALSE) presets xAxis, yAxis and first serie.
11+
#' @param load Name(s) of plugin(s) to load. Could be a character vector or comma-delimited string. default NULL.\cr
12+
#' Built-in plugins: \cr \itemize{
13+
#' \item leaflet - Leaflet maps with customizable tiles, see \href{https://github.com/gnijuohz/echarts-leaflet#readme}{source}\cr
14+
#' \item custom - renderers for [ec.band] and ec.ebars \cr
15+
#' } Plugins with one-time installation (popup prompt): \cr \itemize{
16+
#' \item 3D - 3D charts and WebGL acceleration, see \href{https://github.com/ecomfe/echarts-gl}{source} and \href{https://echarts.apache.org/en/option-gl.html#series}{docs} \cr
17+
#' \item world - world map with country boundaries, see \href{https://github.com/apache/echarts/tree/master/test/data/map/js}{source} \cr
18+
#' \item liquid - liquid fill, see \href{https://github.com/ecomfe/echarts-liquidfill}{source} \cr
19+
#' \item gmodular - graph modularity, see \href{https://github.com/ecomfe/echarts-graph-modularity}{source} \cr
20+
#' \item wordcloud - cloud of words, see \href{https://github.com/ecomfe/echarts-wordcloud}{source} \cr
21+
#' } Install you own plugins with [ec.plugjs].
1322
#' @param width,height A valid CSS unit (like \code{'100\%'},
1423
#' \code{'500px'}, \code{'auto'}) or a number, which will be coerced to a
1524
#' string and have \code{'px'} appended.
@@ -21,24 +30,24 @@
2130
#'
2231
#' @details Widgets are defined in \href{https://www.htmlwidgets.org/develop_intro.html}{htmlwidgets}.
2332
#' This command creates one with \code{\link[htmlwidgets]{createWidget}}, then adds some EchartsJS features to it.\cr
24-
#' It also presets values for xAxis,yAxis,dataset and series. The user can overwrite them if needed.
33+
#' It may preset values for xAxis,yAxis,series and dataset, which user can overwrite if needed.
2534
#'
2635
#' @examples
2736
#' # basic scatter chart from a data.frame, using presets
2837
#' cars %>% ec.init()
2938
#'
3039
#' @import htmlwidgets
31-
#'
40+
#'
3241
#' @export
33-
ec.init <- function( df = NULL, load = NULL,
42+
ec.init <- function( df = NULL, group1 = 'scatter', preset = TRUE, load = NULL,
3443
width = NULL, height = NULL, elementId = NULL,
35-
renderer = 'canvas', preset = TRUE, group1 = TRUE, js = NULL, ...) {
44+
renderer = 'canvas', js = NULL, ...) {
3645

3746
opts <- list(...)
3847
if (preset)
3948
opts <- append(opts, list(
40-
xAxis = list(list()),
41-
yAxis = list(list()),
49+
xAxis = list(ec=''),
50+
yAxis = list(ec=''),
4251
series = list(list())
4352
))
4453

@@ -60,12 +69,12 @@ ec.init <- function( df = NULL, load = NULL,
6069
x$opts$series[[1]] <- list(type='scatter')
6170

6271
if (!is.null(df)) {
63-
# data.frame given, assign to dataset
72+
# if data.frame given, assign to dataset regardless of parameter preset
6473
if (!'data.frame' %in% class(df))
6574
stop('df must be a data.frame', call. = FALSE)
6675

6776
# grouping uses transform - a v.5 feature
68-
if (group1 && dplyr::is.grouped_df(df)) {
77+
if (!is.null(group1) && dplyr::is.grouped_df(df)) {
6978
grnm <- dplyr::group_vars(df)[[1]] # group1 means just 1st one
7079
df <- df %>% dplyr::relocate(grnm, .after = dplyr::last_col())
7180
x$opts$dataset <- list(list(source = ec.data(df)))
@@ -79,12 +88,12 @@ ec.init <- function( df = NULL, load = NULL,
7988
txfm <- append(txfm, list(list(transform = list(
8089
type='filter', config=list(dimension=grnm, '='=srch4)))))
8190
x$opts$series[[k]] <- list(
82-
type='scatter', datasetIndex=k, name=i)
91+
type=group1, datasetIndex=k, name=i)
8392
x$opts$legend$data <- append(x$opts$legend$data, list(list(name=i)))
8493
}
8594
x$opts$dataset <- append(x$opts$dataset, txfm)
8695
}
87-
else if (preset)
96+
else
8897
x$opts$dataset <- list(list(source = ec.data(df)))
8998
}
9099

@@ -115,21 +124,11 @@ ec.init <- function( df = NULL, load = NULL,
115124
if (length(load)==1 && grepl(',', load, fixed=TRUE))
116125
load <- unlist(strsplit(load, ','))
117126

118-
if ('3D' %in% load && preset) {
119-
wt$x$opts$xAxis <- NULL
120-
wt$x$opts$yAxis <- NULL
121-
wt$x$opts$series[[1]] <- NULL
122-
wt$x$opts$grid3D <- list(list())
123-
wt$x$opts$xAxis3D <- list(list())
124-
wt$x$opts$yAxis3D <- list(list())
125-
wt$x$opts$zAxis3D <- list(list())
126-
}
127-
128127
path <- system.file('js', package = 'echarty')
129128
dep <- NULL
130129
if ('leaflet' %in% load) {
131130
if (preset) {
132-
# customize for leaflet
131+
# customizations for leaflet
133132
wt$x$opts$dataset <- NULL # dataset not suitable, data must be in series
134133
wt$x$opts$xAxis <- NULL
135134
wt$x$opts$yAxis <- NULL
@@ -141,7 +140,7 @@ ec.init <- function( df = NULL, load = NULL,
141140
tiles = list( list(urlTemplate = urltls))
142141
)
143142

144-
# note: leaflet user data should be ordered (lon,lat)
143+
# leaflet user data should be ordered (lon,lat)!
145144
if (!is.null(df))
146145
wt$x$opts$series[[1]]$data <- ec.data(df, TRUE)
147146
wt$x$opts$series[[1]]$coordinateSystem <- 'leaflet'
@@ -154,30 +153,106 @@ ec.init <- function( df = NULL, load = NULL,
154153
wt$dependencies <- append(wt$dependencies, htmlwidgets::getDependency('leaflet'))
155154
wt$dependencies <- append(wt$dependencies, list(dep))
156155
}
157-
## will be implemented later as manual or dynamic load on-demand, world.js is too big to include in echarty
158-
# if ('geo' %in% load) {
159-
# dep <- htmltools::htmlDependency(
160-
# name = 'world',
161-
# version = '1.0.0', src = c(file = path),
162-
# script = 'world.js'
163-
# )
164-
# wt$dependencies <- append(wt$dependencies, list(dep))
165-
# }
166-
if ('GL' %in% load) {
167-
dep <- htmltools::htmlDependency(
168-
name = 'gl',
169-
version = '2.0.1', src = c(file = path),
170-
script = 'echarts-gl.min.js'
171-
)
172-
wt$dependencies <- append(wt$dependencies, list(dep))
173-
}
174156
if ('custom' %in% load) {
175157
dep <- htmltools::htmlDependency(
176158
name = 'renderers', version = '1.0.2',
177159
src = c(file = path), script = 'renderers.js')
178160
wt$dependencies <- append(wt$dependencies, list(dep))
179161
}
180162

163+
# Plugins implemented as dynamic load on-demand
164+
if ('3D' %in% load) {
165+
if (preset) {
166+
wt$x$opts$xAxis <- NULL # replace 2D presets with 3D
167+
wt$x$opts$yAxis <- NULL
168+
wt$x$opts$series[[1]] <- NULL
169+
wt$x$opts$grid3D <- list(list()) # todo list(ec='')?
170+
wt$x$opts$xAxis3D <- list(list())
171+
wt$x$opts$yAxis3D <- list(list())
172+
wt$x$opts$zAxis3D <- list(list())
173+
}
174+
wt <- ec.plugjs(wt, 'https://cdn.jsdelivr.net/npm/echarts-gl@2.0.1/dist/echarts-gl.min.js')
175+
}
176+
if ('world' %in% load)
177+
wt <- ec.plugjs(wt, 'https://cdn.jsdelivr.net/npm/echarts@4.9.0/map/js/world.js')
178+
179+
if ('liquid' %in% load)
180+
wt <- ec.plugjs(wt, 'https://cdn.jsdelivr.net/npm/echarts-liquidfill@3.0.0/dist/echarts-liquidfill.min.js')
181+
182+
if ('gmodular' %in% load)
183+
wt <- ec.plugjs(wt, 'https://github.com/ecomfe/echarts-graph-modularity/raw/master/dist/echarts-graph-modularity.min.js')
184+
185+
if ('wordcloud' %in% load)
186+
wt <- ec.plugjs(wt, 'https://cdn.jsdelivr.net/npm/echarts-wordcloud@2.0.0/dist/echarts-wordcloud.min.js')
187+
188+
# load unknown installed plugins
189+
unk <- load[! load %in% c('leaflet','custom','3D','world','liquid','gmodular','wordcloud')]
190+
for(p in unk) wt <- ec.plugjs(wt, p)
191+
192+
return(wt)
193+
}
194+
195+
196+
#' Install Javascript plugin from URL source
197+
#'
198+
#' @param wt A widget to add dependency to, see \code{\link[htmlwidgets]{createWidget}}
199+
#' @param source URL of the uninstalled Javascript plugin, \cr
200+
#' or name of an installed plugin file, suffix .js included. Default is NULL.
201+
#' @return A widget with JS dependency added if successful, otherwise input wt
202+
#'
203+
#' @details When \emph{source} is URL, the plugin file is installed with a popup prompt to the user.\cr
204+
#' When \emph{source} is just a file name (xxx.js), it is assumed installed and only a dependency is added. The latter option is for internal usage by echarty.
205+
#'
206+
#' @examples
207+
#' # import map plugin and display two (lon,lat) locations
208+
#' p <- ec.init() %>% ec.plugjs(
209+
#' 'https://raw.githubusercontent.com/apache/echarts/master/test/data/map/js/china-contour.js')
210+
#' p$x$opts <- list(
211+
#' geo = list(map='china-contour', roam=TRUE),
212+
#' legend = list(data = list(list(name = 'Geo'))),
213+
#' series = list(list( name = 'Geo',
214+
#' type = 'scatter', coordinateSystem = 'geo',
215+
#' symbolSize = 9, itemStyle = list(color='red'),
216+
#' data = list(list(value=c(113, 40)), list(value=c(118, 39))) ))
217+
#' )
218+
#' p
219+
#'
220+
#' @importFrom utils askYesNo download.file
221+
#'
222+
#' @export
223+
ec.plugjs <- function(wt=NULL, source=NULL) {
224+
if (missing(wt))
225+
stop('ec.plugjs expecting widget', call. = FALSE)
226+
if (is.null(source)) return(wt)
227+
fname <- basename(source)
228+
if (!endsWith(fname, '.js'))
229+
stop('ec.plugjs expecting .js suffix', call. = FALSE)
230+
path <- system.file('js', package = 'echarty')
231+
ffull <- paste0(path,'/',fname)
232+
if (!file.exists(ffull)) {
233+
if (!startsWith(source, 'http'))
234+
stop('ec.plugjs expecting URL source', call. = FALSE)
235+
prompt <- paste0('One-time installation of plugin\n',fname,'\n Would you like to proceed ?')
236+
ans <- FALSE
237+
if (interactive())
238+
ans <- askYesNo(prompt)
239+
if (is.na(ans)) ans <- FALSE # was cancelled
240+
if (ans) {
241+
try(withCallingHandlers(
242+
download.file(source, ffull), # method = "libcurl"),
243+
warning = function(w) {
244+
cat('ec.plugjs Error:', sub(".+HTTP status was ", "", w))
245+
ans <- FALSE
246+
}),
247+
silent = TRUE)
248+
}
249+
if (!ans) return(wt)
250+
}
251+
dep <- htmltools::htmlDependency(
252+
name = fname, version = '1.0.0', src = c(file = path),
253+
script = fname
254+
)
255+
wt$dependencies <- append(wt$dependencies, list(dep))
181256
return(wt)
182257
}
183258

@@ -221,7 +296,7 @@ ec.data <- function(df, series=FALSE) {
221296
#'
222297
#' @details The coordinates of the two boundaries are merged into a polygon and displayed as one.
223298
#' @export
224-
ec.sband <- function(df=NULL, lower=NULL, upper=NULL, ...) {
299+
ec.band <- function(df=NULL, lower=NULL, upper=NULL, ...) {
225300
if (is.null(df) || is.null(lower) || is.null(upper))
226301
stop('df, lower and upper are all required', call. = FALSE)
227302
if (!'data.frame' %in% class(df))
@@ -243,6 +318,22 @@ ec.sband <- function(df=NULL, lower=NULL, upper=NULL, ...) {
243318
}
244319

245320

321+
#' Translator Assistant
322+
#'
323+
#' Translate Javascript data objects to R
324+
#'
325+
#' @return none
326+
#'
327+
#' @details To learn by examples in Javascript from \href{https://echarts.apache.org/examples/en/}{Echarts}
328+
#' @export
329+
ec.js2r <- function() {
330+
if (interactive())
331+
shiny::runGist('https://gist.github.com/helgasoft/819035e853d9889ba02cb69ecc587f34',quiet=TRUE)
332+
return(NULL)
333+
}
334+
335+
336+
246337
# ----------- Shiny --------------
247338
#'
248339
#' Shiny: UI chart

0 commit comments

Comments
 (0)