---
title: "Interactive Annotation of a ggplot"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Interactive Annotation of a ggplot}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
## Description
This is a moderately complex example where the user can draw on a rendered plot
and then save this plot to a named file.
Code features:
* pop-ups
* button command
* binding events on the canvas to functions
# Video
Since an interactive window cannot be captured in a vignette, a video
screen capture has been taken of the window and included below.
# Final image
The final saved image:
# Code
```{r eval=FALSE}
library(ggplot2)
library(tickle)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# At the time of definining the button action, need to define a variable
# which will later contain the actual canvas
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
canvas <- NULL
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# When the button is pressed:
# - request name of file to save from the user
# - save the canvas
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
save_action <- function() {
filename <- popup_save_file()
if (length(filename) == 0) { return() }
canvas_save(
canvas = canvas,
filename = filename
)
message("Saved canvas to: ", filename)
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# set some global variables for the events
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drawing <- FALSE
lastx <- NA
lasty <- NA
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# If a button is pressed, start drawing
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mouse_press_action <- function(x, y) {
drawing <<- TRUE
lastx <<- x
lasty <<- y
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# When the button is released, stop drawing
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mouse_release_action <- function() {
drawing <<- FALSE
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# If the mouse is moving, and the 'drawing' mode is TRUE,
# then draw a line segment from the last position to the current mouse position
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mouse_move_action <- function(x, y) {
if (drawing) {
canvas_line(canvas, c(lastx, x), c(lasty, y), fill = '#ff4444', width = 2)
lastx <<- x
lasty <<- y
}
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Simple UI spec
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ui_spec <- tic_window(
tic_col(
pack_def = pack_opts(pady = 2),
tic_label("ggreview", style = 'h3'),
tic_label("Annotate a plot object and then save to file."),
tic_button("Save Canvas to File", style = "success", command = save_action),
tic_canvas(
width = 800, height = 600, scrollbars = FALSE,
bind = list(
bind_opts("Button" , mouse_press_action),
bind_opts("ButtonRelease", mouse_release_action),
bind_opts("Motion" , mouse_move_action)
))
)
)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render the UI to screen
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
win <- render_ui(ui_spec)
canvas <- win$col$canvas_frame$canvas
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Render a plot to the canvas
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p <- ggplot(mtcars) + geom_point(aes(mpg, wt))
canvas_plot(canvas, plot = p, width = 800, height = 600)
```