Neighbor highlighting via mouseover and click at the same time
1 |
#' Add forceAtlas2
|
|
2 |
#'
|
|
3 |
#' Implementation of \href{http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679}{forceAtlas2}.
|
|
4 |
#'
|
|
5 |
#' @inheritParams sg_nodes
|
|
6 |
#' @param proxy An object of class \code{sigmajsProxy} as returned by \code{\link{sigmajsProxy}}.
|
|
7 |
#' @param delay Milliseconds after which the layout algorithm should stop running.
|
|
8 |
#' @param data \code{data.frame} holding \code{delay} column.
|
|
9 |
#' @param cumsum Whether to compute the cumulative sum of the delay.
|
|
10 |
#' @param ... Any parameter, see \href{https://github.com/jacomyal/sigma.js/tree/master/plugins/sigma.layout.forceAtlas2}{official documentation}.
|
|
11 |
#' @param refresh Whether to refresh the graph after node is dropped, required to take effect.
|
|
12 |
#'
|
|
13 |
#'
|
|
14 |
#' @section Functions:
|
|
15 |
#' \itemize{
|
|
16 |
#' \item{\code{sg_force}, \code{sg_force_start} starts the forceAtlas2 layout}
|
|
17 |
#' \item{\code{sg_force_stop} stops the forceAtlas2 layout after a \code{delay} milliseconds}
|
|
18 |
#' \item{\code{sg_force_restart_p} proxy to re-starts (\code{kill} then \code{start}) the forceAtlas2 layout, the options you pass to this function are applied on restart. If forceAtlas2 has not started yet it is launched.}
|
|
19 |
#' \item{\code{sg_force_start_p} proxy to start forceAtlas2.}
|
|
20 |
#' \item{\code{sg_force_stop_p} proxy to stop forceAtlas2.}
|
|
21 |
#' \item{\code{sg_force_kill_p} proxy to ompletely stops the layout and terminates the assiociated worker. You can still restart it later, but a new worker will have to initialize.}
|
|
22 |
#' \item{\code{sg_force_config_p} proxy to set configurations of forceAtlas2.}
|
|
23 |
#' \item{\code{sg_force_restart} Restarts (kills then starts) forceAtlas2 at given delay.}
|
|
24 |
#' }
|
|
25 |
#'
|
|
26 |
#' @details The delay helps for build dynamic visualisations where nodes and edges do not appear all at the same time.
|
|
27 |
#' How the delay works depends on the \code{cumsum} parameter. if \code{TRUE} the function computes the cumulative sum
|
|
28 |
#' of the delay to effectively add each row one after the other: delay is thus applied at each row (number of seconds to wait
|
|
29 |
#' before the row is added *since the previous row*). If \code{FALSE} this is the number of milliseconds to wait before the node or
|
|
30 |
#' edge is added to the visualisation; \code{delay} is used as passed to the function.
|
|
31 |
#'
|
|
32 |
#' @examples
|
|
33 |
#' nodes <- sg_make_nodes(50)
|
|
34 |
#' edges <- sg_make_edges(nodes, 100)
|
|
35 |
#'
|
|
36 |
#' sigmajs() %>%
|
|
37 |
#' sg_nodes(nodes, id, label, size) %>%
|
|
38 |
#' sg_edges(edges, id, source, target) %>%
|
|
39 |
#' sg_force() %>%
|
|
40 |
#' sg_force_stop() # stop force after 5 seconds
|
|
41 |
#'
|
|
42 |
#' @return Their first arguments, either \code{sg} or \code{proxy}.
|
|
43 |
#'
|
|
44 |
#' @seealso \href{https://github.com/jacomyal/sigma.js/tree/master/plugins/sigma.layout.noverlap}{official documentation}
|
|
45 |
#'
|
|
46 |
#' @name force
|
|
47 |
#' @export
|
|
48 |
sg_force <- function(sg, ...) { |
|
49 |
|
|
50 | 1 |
if (missing(sg)) |
51 | 1 |
stop("missing sg", call. = FALSE) |
52 |
|
|
53 | 1 |
.test_sg(sg) |
54 |
|
|
55 | 1 |
sg$x$force <- list(...) |
56 | 1 |
sg |
57 |
}
|
|
58 |
|
|
59 |
#' @rdname force
|
|
60 |
#' @export
|
|
61 |
sg_force_start <- sg_force
|
|
62 |
|
|
63 |
#' @rdname force
|
|
64 |
#' @export
|
|
65 |
sg_force_stop <- function(sg, delay = 5000) { |
|
66 |
|
|
67 | 1 |
if (missing(sg)) |
68 | 1 |
stop("missing sg", call. = FALSE) |
69 |
|
|
70 | 1 |
if (!inherits(sg, "sigmajs")) |
71 | 1 |
stop("sg must be of class sigmajs", call. = FALSE) |
72 |
|
|
73 | 1 |
sg$x$forceStopDelay <- delay |
74 | 1 |
sg |
75 |
}
|
|
76 |
|
|
77 |
#' @rdname force
|
|
78 |
#' @export
|
|
79 |
sg_force_restart_p <- function(proxy, ..., refresh = TRUE) { |
|
80 |
|
|
81 |
if (missing(proxy)) |
|
82 |
stop("must pass proxy", call. = FALSE) |
|
83 |
|
|
84 |
.test_proxy(proxy) |
|
85 |
|
|
86 |
message <- list(id = proxy$id, data = list(...), refresh = refresh) |
|
87 |
|
|
88 |
proxy$session$sendCustomMessage("sg_force_restart_p", message) |
|
89 |
|
|
90 |
return(proxy) |
|
91 |
}
|
|
92 |
|
|
93 |
#' @rdname force
|
|
94 |
#' @export
|
|
95 |
sg_force_restart <- function(sg, data, delay, cumsum = TRUE) { |
|
96 |
|
|
97 |
if (missing(data) || missing(delay) || missing(sg)) |
|
98 |
stop("must pass sg, data and delay", call. = FALSE) |
|
99 |
|
|
100 |
.test_sg(sg) |
|
101 |
|
|
102 |
delay_col <- eval(substitute(delay), data) |
|
103 |
if (isTRUE(cumsum)) |
|
104 |
delay_col <- cumsum(delay_col) |
|
105 |
|
|
106 |
delay_table <- dplyr::tibble(sigmajsdelay = delay_col) |
|
107 |
|
|
108 |
# build data
|
|
109 |
delay <- .build_data(data) %>% |
|
110 |
dplyr::bind_cols(delay_table) %>% |
|
111 |
dplyr::arrange(sigmajsdelay) %>% |
|
112 |
.as_list() |
|
113 |
|
|
114 |
sg$x$forceRestartDelay <- append(sg$x$forceRestartDelay, delay) |
|
115 |
sg |
|
116 |
}
|
|
117 |
|
|
118 |
#' @rdname force
|
|
119 |
#' @export
|
|
120 |
sg_force_start_p <- function(proxy, ..., refresh = TRUE) { |
|
121 |
|
|
122 |
if (missing(proxy)) |
|
123 |
stop("must pass proxy", call. = FALSE) |
|
124 |
|
|
125 |
.test_proxy(proxy) |
|
126 |
|
|
127 |
message <- list(id = proxy$id, data = list(...), refresh = refresh) |
|
128 |
|
|
129 |
proxy$session$sendCustomMessage("sg_force_start_p", message) |
|
130 |
|
|
131 |
return(proxy) |
|
132 |
}
|
|
133 |
|
|
134 |
#' @rdname force
|
|
135 |
#' @export
|
|
136 |
sg_force_stop_p <- function(proxy) { |
|
137 |
|
|
138 |
if (missing(proxy)) |
|
139 |
stop("must pass proxy", call. = FALSE) |
|
140 |
|
|
141 |
.test_proxy(proxy) |
|
142 |
|
|
143 |
message <- list(id = proxy$id) |
|
144 |
|
|
145 |
proxy$session$sendCustomMessage("sg_force_stop_p", message) |
|
146 |
|
|
147 |
return(proxy) |
|
148 |
}
|
|
149 |
|
|
150 |
#' @rdname force
|
|
151 |
#' @export
|
|
152 |
sg_force_kill_p <- function(proxy) { |
|
153 |
|
|
154 |
if (missing(proxy)) |
|
155 |
stop("must pass proxy", call. = FALSE) |
|
156 |
|
|
157 |
.test_proxy(proxy) |
|
158 |
|
|
159 |
message <- list(id = proxy$id) |
|
160 |
|
|
161 |
proxy$session$sendCustomMessage("sg_force_kill_p", message) |
|
162 |
|
|
163 |
return(proxy) |
|
164 |
}
|
|
165 |
|
|
166 |
#' @rdname force
|
|
167 |
#' @export
|
|
168 |
sg_force_config_p <- function(proxy, ...) { |
|
169 |
|
|
170 |
if (missing(proxy)) |
|
171 |
stop("must pass proxy", call. = FALSE) |
|
172 |
|
|
173 |
.test_proxy(proxy) |
|
174 |
|
|
175 |
message <- list(id = proxy$id, data = list(...)) |
|
176 |
|
|
177 |
proxy$session$sendCustomMessage("sg_force_config_p", message) |
|
178 |
|
|
179 |
return(proxy) |
|
180 |
}
|
Read our documentation on viewing source code .