use this function on Shiny UI or R markdown to create the image editing area.
canvas(
canvasID,
title = "drawer",
height = "100vh",
width = "100%",
logo_src = "drawer/img/drawer.png",
log_link = "https://github.com/lz100/drawer",
on_start = TRUE,
rmarkdown = FALSE
)
string, an unique HTML ID
string, title of the canvas
string, css value of initial height of the canvas, like "100vh" for full height current window, "50vh" for half.
string, css value of initial width of the canvas
string, link of an image you want to display as logo on the top left
string, a link, when the logo is clicked, where should it jump to
TRUE
or a CSS selector. See details
bool, are you using inside R markdown? If yes, drawer will copy
all image icons that required by the canvas to current directory to ./drawer/img/...
a HTML component to be added to a Shiny app or document
If you are not working in Shiny or R markdown, you need to add the required full "Bootstrap3" javascript and CSS + latest "jquery" dependencies by yourself.
There are two options for canvas height and width:
dynamic CSS units like "100vh" (viewpoint height), "100vw" (view point width), or "100%" for both. This kind of units adapt to all kinds of user screen settings.
fixed unit, px
(pixels). This does not change across users, but fixes
the on_start
problem (read below).
height
, css style vh
is safer than %
is not safe, unless the parent
has some defined height, "%" will work. Otherwise, if the parent height is "auto"
or not defined, and you choose "100%", canvas will still have 0 height.
Width usually does not have this problem. As long as an element is displayed, it has some width.
on_start
This argument specify if you want to initiate the canvas when the document is loaded.
If TRUE
, then when the document loading is done, start the canvas. The problem
is if you set the height to be "vh" (view height) units and if the canvas is
hidden, like in a different tab and not displayed on start, the view height is
0, because it is hidden on another tab (display property is none
), so it
will cause the canvas cannot be initiated properly.
The solution is to bind the initiation with a clicking event, like on a tab or a button.
For example, make a button on the second tab and bind on_start
to that button:
on_start = "#buttonID"
. Then when users click on that button, canvas initiate.
Remember this is a Jquery CSS selector, which means you need to append "#" in
front your button ID.
If you want to do it automatically, like clicking on a certain tab, some CSS knowledge may required. For example, in Shiny, you can use shiny::tabsetPanel to create a tab panel.
tabsetPanel(id = "tabs",
tabPanel("Tab A", value = "A", ...),
tabPanel("Tab B", value = "B", ...),
...
)
Then, bind to it canvas(on_start = '#tabs li a[data-value="B"]', ...)
.
This means we are selecting the element with ID "tabs", which is the main tabsetPanel
ID, then a list item (li
) which is the tab titles you see on UI, and finally, the
link jump to tab B, (a[data-value="B"]
). See examples for a real case.
Another way to fix it is by given the height
and width
a fixed pixel unit:
canvas(
canvasID = "canvas_f",
height = "900px",
width = "1500px"
)
# basic usage
if(interactive()){
library(shiny)
ui <- fluidPage(
h3("Try to drag pictures locally to canvas"),
canvas("canvas_a")
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
}
# multiple canvas on a page
if(interactive()){
library(shiny)
ui <- fluidPage(
h3("multiple canvas on a page"),
p("They are independent"),
p("Dragging from one canvas to another is not supported currently"),
column(6, canvas("canvas_left")),
column(6, canvas("canvas_right"))
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
}
# with capture buttons buttons
if(interactive()){
library(shiny)
library(ggplot2)
ui <- fluidPage(
fluidRow(
id = "new_row",
column(
6,
h3("this is a title"),
column(6, tags$label("plot 1"), plotOutput("plot_1")),
column(6, tags$label("plot 2"), plotOutput("plot_2")),
),
column(
6,
h2("To canvas buttons"),
h4("pure button with `toCanvasBtn`"),
toCanvasBtn(
dom = "plot_1",
label = "capture plot 1",
canvasID = "canvas_b"
), br(),
toCanvasBtn(
dom = "capture_button",
label = "capture this button itself",
canvasID = "canvas_b",
id = "capture_button"
), br(),
toCanvasBtn(
dom = "#new_row .col-sm-6:first-of-type",
label = "complex selector to select left column",
canvasID = "canvas_b",
isID = FALSE
), br(),
h4("button text input for any part of document with `toCanvasBtn`"),
toCanvasTextBtn(
label = "try #plot_2 to for plot 2 or other selector",
canvasID = "canvas_b",
text_value = "#plot_2"
)
)
),
canvas("canvas_b")
)
server <- function(input, output, session) {
output$plot_1 <- renderPlot({
ggplot(mpg, aes(cty, hwy)) +
geom_count(col="tomato3", show.legend=F)
})
output$plot_2 <- renderPlot({
ggplot(mpg, aes(cty, hwy)) +
geom_point()
})
}
shinyApp(ui, server)
}
# start canvas as hidden, initiate later in tab panels
if(interactive()){
library(shiny)
ui <- fluidPage(
tabsetPanel(
id = "tabs",
tabPanel(
"Home page",
value = "tab_1",
h4("Content on home page ...."),
p("Canvas is hidden on start, go to other tabs")
),
tabPanel(
"Canvas C",
value = "tab_2",
markdown(
'
# canvas hidden on start
In this example, you will see if the canvas is hidden,
not on the first tab in a `tabsetPanel`, or other similar
UI where you do not see canvas on start. Then, the canvas
cannot be initiate properly using the default height value (100vh).
Using the dynamic computed CSS height like "100%", or "100vh" with "hidden"
(display = none) elements give the height of `0` on start.
So, you **should not see the canvas** on this tab, but a broken
structure and no canvas grid.
To fix it, either give it a fixed `height` and `width` pixel unit, like
- `height = "800px"`, `width = "1500px"`
or bind the initiation event to a click of a button, the tab title or
any other element you specify with the `on_start` argument. See the
example code and watch how we do it in "canvas D-F".
'
),
canvas(canvasID = "canvas_c")
),
tabPanel(
"Canvas D",
value = "tab_3",
h4("Initiate canvas by a button"),
actionButton("start_canvas", "Start Canvas C"),
canvas(
canvasID = "canvas_d",
on_start = "#start_canvas"
)
),
tabPanel(
"Canvas E",
value = "tab_4",
h4("Initiate canvas by clicking tab title"),
p("Canvas initiate when first time users come to this tab"),
canvas(
canvasID = "canvas_e",
on_start = "#tabs li a[data-value='tab_4']"
)
),
tabPanel(
"Canvas F",
value = "tab_5",
h4("Initiate canvas with fixed height and width"),
canvas(
canvasID = "canvas_f",
height = "800px",
width = "1500px"
)
)
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
}