Skip to content

Commit 613d590

Browse files
committed
feat: add linked parameter to opts_hover() and opts_selection()
- Share hover/selection state between geometry (data-id) and legend (key-id) elements. - Added linked_scale Shiny example to demonstrate the feature. see #330
1 parent 530721d commit 613d590

File tree

13 files changed

+157
-10
lines changed

13 files changed

+157
-10
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: ggiraph
33
Title: Make 'ggplot2' Graphics Interactive
4-
Version: 0.9.5.002
4+
Version: 0.9.5.003
55
Authors@R: c(
66
person("David", "Gohel", , "david.gohel@ardata.fr", role = c("aut", "cre")),
77
person("Panagiotis", "Skintzos", , "sigmapi@posteo.net", role = "aut"),

NEWS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# ggiraph 0.9.5
22

3+
## Feature
4+
5+
- `opts_hover()` and `opts_selection()` gain a new `linked` parameter. When
6+
`linked = TRUE`, hover and selection states are shared between geometry
7+
elements (`data-id`) and legend/guide elements (`key-id`): hovering or
8+
clicking a legend key highlights or selects the corresponding geometries,
9+
and vice versa (#330).
10+
311
## Issues
412

513
- fix label_interactive broken by the new V4 ggplot2 (#348)

R/girafe_options.R

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ opts_tooltip <- function(
167167
#' By default (`NULL`) it's set to `Infinity` which means that there is no distance limit.
168168
#' Setting it to 50, for example, it will hover the nearest element that has
169169
#' at maximum 50 SVG units (pixels) distance from the mouse cursor.
170+
#' @param linked if TRUE, hovering a legend/guide element (`key-id`) will
171+
#' also highlight the corresponding geometry elements (`data-id`) and vice versa.
170172
#' @note **IMPORTANT**: When applying a `fill` style with the `css` argument,
171173
#' be aware that the browser's CSS engine will apply it also to line elements,
172174
#' if there are any that use the hovering feature. This will cause an undesired effect.
@@ -192,7 +194,7 @@ opts_tooltip <- function(
192194
#' @export
193195
#' @family girafe animation options
194196
#' @seealso [girafe_css()], [girafe_css_bicolor()]
195-
opts_hover <- function(css = NULL, reactive = FALSE, nearest_distance = NULL) {
197+
opts_hover <- function(css = NULL, reactive = FALSE, nearest_distance = NULL, linked = FALSE) {
196198
css <- check_css(
197199
css,
198200
default = "fill:orange;stroke:gray;",
@@ -211,8 +213,11 @@ opts_hover <- function(css = NULL, reactive = FALSE, nearest_distance = NULL) {
211213
call. = FALSE
212214
)
213215
}
216+
if (!is_valid_logical(linked)) {
217+
abort("`linked` must be a scalar logical", call = NULL)
218+
}
214219

215-
x <- list(css = css, reactive = reactive, nearest_distance = nearest_distance)
220+
x <- list(css = css, reactive = reactive, nearest_distance = nearest_distance, linked = linked)
216221
class(x) <- "opts_hover"
217222
attr(x, "explicit_args") <- names(match.call())[-1]
218223
x
@@ -292,6 +297,8 @@ opts_hover_theme <- function(css = NULL, reactive = FALSE) {
292297
#' documentation examples or R Markdown output).
293298
#' @param selected character vector, id to be selected when the graph will be
294299
#' initialized.
300+
#' @param linked if TRUE, selecting a legend/guide element (`key-id`) will
301+
#' also select the corresponding geometry elements (`data-id`) and vice versa.
295302
#' @note **IMPORTANT**: When applying a `fill` style with the `css` argument,
296303
#' be aware that the browser's CSS engine will apply it also to line elements,
297304
#' if there are any that use the selection feature. This will cause an undesired effect.
@@ -322,7 +329,8 @@ opts_selection <- function(
322329
css = NULL,
323330
type = c("multiple", "single", "none"),
324331
only_shiny = TRUE,
325-
selected = character(0)
332+
selected = character(0),
333+
linked = FALSE
326334
) {
327335
css <- check_css(
328336
css,
@@ -334,12 +342,16 @@ opts_selection <- function(
334342
if (!is_valid_logical(only_shiny)) {
335343
abort("`only_shiny` must be a scalar logical", call = NULL)
336344
}
345+
if (!is_valid_logical(linked)) {
346+
abort("`linked` must be a scalar logical", call = NULL)
347+
}
337348

338349
x <- list(
339350
css = css,
340351
type = type,
341352
only_shiny = only_shiny,
342-
selected = as.character(selected)
353+
selected = as.character(selected),
354+
linked = linked
343355
)
344356
class(x) <- "opts_selection"
345357
attr(x, "explicit_args") <- names(match.call())[-1]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Title: Interactive legend
2+
Author: David Gohel
3+
AuthorUrl: https://www.ardata.fr
4+
License: GPL-3
5+
DisplayMode: Showcase
6+
Tags: reactive-selection
7+
Type: Shiny
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Shiny application for linked interactive legend
2+
3+
Hover and selection are linked between legend keys and geometry points using
4+
`opts_hover(linked = TRUE)` and `opts_selection(linked = TRUE)`.
5+
Clicking a legend key selects the corresponding points and vice versa.
6+
A summary of the selection is rendered.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
library(ggplot2)
2+
library(ggiraph)
3+
4+
gg <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width,
5+
color = Species, data_id = Species)) +
6+
geom_point_interactive(size = 3) +
7+
theme_minimal() +
8+
scale_colour_manual_interactive(
9+
data_id = c("setosa" = "setosa", "versicolor" = "versicolor", "virginica" = "virginica"),
10+
tooltip = c("setosa" = "setosa", "versicolor" = "versicolor", "virginica" = "virginica"),
11+
values = c("setosa" = "#E41A1C", "versicolor" = "#377EB8", "virginica" = "#4DAF4A")) +
12+
theme(legend.position = "top")
13+
14+
15+
shinyServer(function(input, output, session) {
16+
17+
selected_keys <- reactive({
18+
input$plot_key_selected
19+
})
20+
21+
output$plot <- renderGirafe({
22+
x <- girafe(
23+
code = print(gg), width_svg = 5, height_svg = 5,
24+
options = list(
25+
opts_toolbar(saveaspng = FALSE),
26+
opts_selection(type = "single", linked = TRUE),
27+
opts_selection_key(css = "stroke:black;r:5pt;"),
28+
opts_hover(css = "fill:wheat;stroke:black;stroke-width:3px;cursor:pointer;",
29+
linked = TRUE),
30+
opts_hover_key(css = "stroke:black;r:5pt;cursor:pointer;")
31+
)
32+
)
33+
x
34+
})
35+
36+
output$datatab <- renderTable({
37+
out <- iris[iris$Species %in% selected_keys(), -5]
38+
if( nrow(out) < 1 ) return(NULL)
39+
row.names(out) <- NULL
40+
data.frame( variable = colnames(out),
41+
min = apply(out, 2, min),
42+
mean = colMeans(out),
43+
sd = apply(out, 2, sd),
44+
max = apply(out, 2, max)
45+
)
46+
})
47+
48+
})
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
library(ggiraph)
2+
3+
shinyUI(fluidPage(
4+
tags$h1("ggiraph key selection demo"),
5+
6+
fluidRow(
7+
column(width = 7,
8+
h4("Click a legend key or a point to select: "),
9+
girafeOutput("plot")
10+
),
11+
column(width = 5,
12+
h4("Selection summary"),
13+
tableOutput("datatab")
14+
)
15+
)
16+
)
17+
)

inst/htmlwidgets/girafe.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/opts_hover.Rd

Lines changed: 9 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/opts_selection.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)