---
title: "g6R"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{g6R}
%\VignetteEngine{quarto::html}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
```{r setup, message=FALSE}
library(g6R)
library(shiny)
```
## Graph data
### Data formats
To setup a `{g6R}` graph, you first have to define __node__, __edges__ and __combos__ (collection of nodes), like so:
```{r}
nodes <- data.frame(id = 1:10)
nodes$label <- nodes$id
```
You could also pass these elements as __list__, which will be faster than the dataframe approach since under the hood, `{g6R}` has to send list to JavaScript:
```r
nodes <- lapply(seq_len(10), function(i) {
list(id = i, label = i)
})
```
We then define some random edges:
```{r}
# Set a seed for reproducibility
set.seed(123)
# Define the number of edges to create (e.g., 200 random connections)
num_edges <- 5
# Generate random edges
edges <- data.frame(
source = sample(nodes$id, num_edges, replace = TRUE),
target = sample(nodes$id, num_edges, replace = TRUE)
)
edges$id <- paste0(edges$source, edges$target)
duplicated_id <- which(duplicated(edges$id) == TRUE)
if (length(duplicated_id)) {
edges <- edges[-duplicated_id, ]
}
```
### Performance
If you are dealing with large graphs, you might want to use the `jsonUrl` parameter to __fetch__ the graph data from a hosted JSON file instead. If so, then leave `nodes`, `edges` and `combos` `NULL`. This allows to bypass the serialization of the graph data to JavaScript, which can be slow for large graphs. That's done in the `shinyAppDir(system.file("examples", "json", package = "g6R"))` example.
```{r g6R-json, eval=FALSE, echo = TRUE}
shinyAppDir(system.file("examples", "json", package = "g6R"))
```
```{r shinylive_url_2, echo = FALSE, results = 'asis'}
# extract the code from knitr code chunks by ID
code <- paste0(
c(
"webr::install(\"g6R\", repos = \"https://cynkra.github.io/blockr.webR/\")",
knitr::knit_code$get("g6R-json")
),
collapse = "\n"
)
url <- roxy.shinylive::create_shinylive_url(code, header = FALSE)
```
```{r shinylive_iframe_2, echo = FALSE, eval = TRUE}
tags$iframe(
class = "border border-5 rounded shadow-lg",
src = url,
style = "zoom: 0.75;",
width = "100%",
height = "1100px"
)
```
## Initialise the graph
We leverage `g6` to create an __instance__ of our network:
```{r}
g6(nodes, edges, width = 200, height = 200)
```
As you can see, the nodes don't render well yet. Let's add it some layout.
## Layout
`g6_layout()` allows to pass any supported [layout](https://g6.antv.antgroup.com/en/manual/layout/overview). For this example, we select the `d3_force_layout()`:
```{r}
g <- g6(nodes, edges) |>
g6_layout(d3_force_layout())
g
```
That's better! We could go further by displaying nodes __label__.
## Tweak options
`g6_options()` is your to go tool when it comes to change the style of the graph element such as nodes. Properties are selected from the [documentation](https://g6.antv.antgroup.com/en/manual/element/node/build-in/base-node#main-graphic-style):
```{r}
g <- g |>
g6_options(
node = list(
style = list(
labelBackground = TRUE,
labelBackgroundFill = '#FFB6C1',
labelBackgroundRadius = 4,
labelFontFamily = 'Arial',
labelPadding = c(0, 4),
labelText = JS(
"(d) => {
return d.id
}"
)
)
)
)
g
```
## Plugins
Plugins allowing users to improve the user experience by adding graphical components to the canvas like __minimaps__ or __tooltips__.
We can pass them inside `g6_plugins` either as a character string with a reference to the plugin name or using the correponding function to pass more configuration options:
```r
# Use defaults
g6_plugins("minimap")
# Custom options
g6_plugins(
minimap(size = c(100, 100))
)
```
```{r}
g <- g |>
g6_plugins(
minimap(size = c(100, 100))
)
g
```
## Behaviors
Behaviors correspond to interactions between users and the graph elements, such as dragging the nodes and selecting nodes. Be mindful that not all behaviors are compatible: dragging canvas and canvas elements would require to specify different triggers for each behavior.
With `{g6R}` behaviors can be added with `g6_behaviors`, like plugins:
```{r}
g <- g |>
g6_behaviors(
"zoom-canvas",
drag_element_force(fixed = TRUE),
click_select(
multiple = TRUE,
onClick = JS(
"(e) => {
console.log(e);
}"
)
),
brush_select()
)
g
```
Notice that we can pass __callback__ functions from R to JavaScript. This is useful in combination with Shiny to set custom inputs, for instance.