Putting a leaflet map in a "Picture Frame" in R - css

I am presently in the process of building an R package that allows users to make custom souvenir maps of their flights, road trips and the cities they visit.
I am in the process of trying to figure out how to add a custom title and frame to a leaflet map.
What I have so far
library(leaflet)
library(htmltools)
library(htmlwidgets)
# Custom CSS
tag.map.title <- tags$style(HTML("
.leaflet-control.map-title {
transform: translate(-30%,850%);
position: fixed !important;
left: 50%;
text-align: center;
font-weight: bold;
font-size: 60px;
font-family: 'Brush Script MT'
}
"))
# Adding a title
title <- tags$div(
tag.map.title, HTML("New York, New York!")
)
# Using my custom package
# devtools::install_github("benyamindsmith/mapBliss")
mapBliss::plot_city_view("New York City",
#mapBoxTemplate ="mapbox-template-link",
zoomControl = c(0.15, 0.05, 0.04, -0.003)) %>%
addControl(title, position = "topright", className="map-title")
What I want
I am wondering what is the CSS required if I want to have frames like these? Ideally they would maintain their position when resized also.
(For now, ignore the MapBox theme)

If map and title share a common parent container (e.g. <div>), you can position both relative to their parent container. Remember to set position:relative in the children's CSS.
Example:
library(shiny)
library(leaflet)
ui <- fluidPage(
## see various ways of including CSS: https://shiny.rstudio.com/articles/css.html
tags$head(
tags$style(HTML("
#greetings{top:-8rem;
position:relative;
z-index:1000;
background-color:#f0f0f099;
}
.fancy_border{border:dotted 5em green}
")
)
),
div(class = 'fancy_border', ## set CSS class to style border
div(leafletOutput('map')),
div(id = 'greetings', uiOutput('message'))
)
)
server <- function(input, output) {
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles(providers$Stamen.TonerLite,
options = providerTileOptions(noWrap = TRUE)
) %>%
addMarkers(data = cbind(c(16, 17), c(46, 48)))
})
## note that you can also add CSS classes here:
output$message <- renderUI(h1('Hello from here', class='text-success'))
}
shinyApp(ui, server)
edit: you can style the "picture frame" by setting a class for the parent DIV of both leaflet map and title. Or by having the user choose one of several CSS classes. Alternatively, you can compose a CSS style string (style="...") from user input (colour, width etc.) and re-renderUI this part. Aside: if UI rendering is expensive, you can alternatively set CSS classes/styles client-side.

Related

Can I add an arrow icon to my bsCollapsePanel in R Shiny?

Here is a very simple example of two collapsible panels and I would like to add an icon like an arrow or something to show that it is able to collapse.
library(shinyBS)
shinyApp(
ui =
fluidPage(
bsCollapse(id = "collapseExample", open = c("panel 1, panel 2"),
bsCollapsePanel("panel 1", "First panel content",
style = "info"),
bsCollapsePanel("panel 2", "Second panel content",
style = "warning"))
),
server =
function(input, output, session){
}
)
Also if anyone knows a way to change the css styling of the panels (like color, font size, font, text alignment, background color, etc) that would be awesome!
I did it outside Shiny in this fiddle that allows you to experiment with Bootstrap (which is the underlying basis of shinyBS).
I used this CSS.
<style>
.panel-heading .panel-title a.collapsed:after {
transform: rotate(180deg);
transition: .5s ease-in-out;
}
.panel-heading .panel-title a:after {
content:'⏶';
text-align: right;
float:right;
transition: .5s ease-in-out;
}
.panel-heading .panel-title a:not([class]):after {
transform: rotate(180deg);
}
</style>
The CSS uses the :after selector to place an arrow (as content) behind and displays it on the right-hand side of the panel (i.e. float and text-align). The other two specs a:not([class]) and a.collapsed make sure that the arrow always points into the right direction. The transitions are for show.
Place this CSS inside a tags$head element (instructions here) and it should style your panels accordingly. The head of your sample app should look like this:
shinyApp(
ui =
fluidPage(
tags$head(
# Note the wrapping of the string in HTML()
tags$style(HTML("
<!-- PUT THE CSS HERE without the surrounding <style> tag -->
")),
bsCollapse(id = "coll...
I admit I haven't tested it in a Shiny environment (only in the bootstrap fiddle). But since shinyBS is only a wrapper for Bootstrap it should work.
You can also just put a fontawesome icon next to the title "Panel 1" and "Panel 2".
library(shinyBS)
library(shiny)
shinyApp(
ui =
fluidPage(
bsCollapse(
id = "collapseExample", open = c("panel 1, panel 2"),
bsCollapsePanel(
title = div("Panel 1", icon("angle-down")), "First panel content",
style = "info"),
bsCollapsePanel(
title = div("Panel 2", icon("angle-down")), "Second panel content",
style = "warning"))
),
server =
function(input, output, session){
}
)

Adjust Padding of Shiny Table Using css

Let's say I want to reduce the padding between the left edge of the screen and the first column to maximize real estate on an iPhone. Here's the table:
library(shiny)
library(reactable)
ui <- fluidPage(
theme = "styles.css",
mainPanel(
align = "left",
reactableOutput("table")
)
)
server <- function(input, output, session) {
output$table <- renderReactable({
reactable(iris,
fullWidth = FALSE
)
})
}
shinyApp(ui, server)
And styles.css is:
.container-fluid {
padding-left: 0 !important;
}
This does not work. However, if I use Chrome Inspector to look at the gap, I can manually set padding-left: 0 and the gap narrows.
How do I narrow the gap from within R/Shiny//css?
Check in the inspector in the sources tab if the file is being correctly included. If it still does not work check if there are errors in your css file, that might be preventing the stylesheet from working. Finally, you might have to set the style inline or in the style tag. If you are using Bootstrap then you can use the ml-0 class in the container.

How to change the color of the ColumnVisibility buttons in DT/Shiny

I am building a table using the DT package in a Shiny Dashboard. The table has several columns and I used DT's ColVis functionality to allow users to hide/show only the columns they're interested in.
My question is - is it possible to change the color of those buttons once the Column visibility button is clicked on? As of right now, the colors aren't different enough and its hard to tell which columns are visible and which ones aren't without navigating to the table. I've included a screenshot that shows what I mean. The Site_ID column is not visible in the table, while the Participant_ID column is.
I used inspect element in google chrome to find out the objects name and it looked to be: a.dt-buttons.buttons-columnVisibility, and was under body.skin-blue, div.dt-button-collection.
Using this info I added the following line to my ui.R code:
tags$head(tags$style(HTML(".skin-blue .dt-button-collection .buttons-columnVisibility .active a{background-color: #4d4d4d}")))
But this didn't appear to do anything. Any help on implementing this custom CSS/HTML into my dashboard would be appreciated.
Based on this answer, it looks like the button color needs to be set with background. I also used !important to override the DT button style, although this may not be the best practice.
Here's a small working example:
library(DT)
library(shiny)
ui <- basicPage(
tags$head(
tags$style(
HTML(
".dt-button.buttons-columnVisibility {
background: #FF0000 !important;
color: white !important;
opacity: 0.5;
}
.dt-button.buttons-columnVisibility.active {
background: black !important;
color: white !important;
opacity: 1;
}"
)
)
),
h2("The iris data"),
DT::dataTableOutput("mytable")
)
server <- function(input, output) {
output$mytable = DT::renderDataTable({
datatable(
iris, rownames = FALSE,
extensions = 'Buttons',
options = list(dom = 'Bfrtip', buttons = I('colvis'))
)
})
}
shinyApp(ui, server)

change color actionButton Shiny R

i'm trying to figure out a way to get an actionButton to change color (and possibly other style elements as well.)
The objective is very general and I'll use this for many button responses throughout my complex shinyDashboard App. Simply said: if a button is clicked, or a specific element (i.e. inputslider) changes that is linked to a button, the button should change color.
I usually code my buttons in Shiny like this one:
actionButton(inputId= "RunFullModel", label =icon("tree-deciduous", lib = "glyphicon"),
style = "color: white;
background-color: #35e51d;
position: relative;
left: 3%;
height: 35px;
width: 35px;
text-align:center;
text-indent: -2px;
border-radius: 6px;
border-width: 2px")),
I've been browsing my ass off, but no luck to something that works.
I have been looking at shinyjs by #Dean Attali to do this, but I can only get it to work to change the background of the printed text as in the example below. The part using ToggleClass or AddClass doesn't work for actionButton("x", "y") it seems.
I've also tried to use updateActionButton from the shiny package itself, but this does not seem to allow style = "..." to be included in the command.
library(shiny)
library(shinyjs)
library(shinyBs)
if (interactive()) {
shinyApp(
ui = fluidPage(
useShinyjs(),
inlineCSS(list(.red = "background: red")),
inlineCSS(list(.blue = "style = 'background-color: blue'")),
actionButton("checkbox", "Make it red"),
bsButton("checkbox2", "Make me blue"),
p(id = "element", "Watch what happens to me")
),
server = function(input, output) {
observe({
toggleClass(id = "element", class = "red",
condition = input$checkbox)
})
observe({
toggleCssClass(id = "checkbox2", class = ".blue",
condition = input$checkbox)
})
}
)
}
The demo model of shinyjs is found here: http://deanattali.com/shinyjs/overview#demo and it looks as if the toggleClass works there for the button with id "btn" but there is no code example directly to be found, and the indirect example from another section of the shinyjs page doesn't seem to work.
Option 3 I tried to have the style = "background-color: ....read R variable" part access an R variable that contains the color name, i.e. mycolor <- "red", but that doesn't work either, and my knowledge of javascript is too limited to figure out how to make that work.
So, .... if anyone has an idea how to make the color switching work with shinyjs, or with another method that works with my button coded above, I would highly appreciate it, and grant you my eternal gratitude. (been stuck on this for weeks now with this issue)
Mark
p.s. i've looked into bsButtons as well but they are too limited for what I want with the default class options.
That should be doable in "pure" shiny:
Use renderUI() to create the button and insert conditions to check if the button was clicked already.
I decided to store the information (whether a button was clicked) within a reactiveVariable as you wrote that you plan to trigger the color change "if a button is clicked, or a specific element (i.e. inputslider) changes that is linked to a button". So you could also change the global$clicked from other inputs.
library(shiny)
shinyApp(
ui = fluidPage(
uiOutput("button")
),
server = function(input, output) {
global <- reactiveValues(clicked = FALSE)
observe({
if(length(input$RunFullModel)){
if(input$RunFullModel) global$clicked <- TRUE
}
})
output$button <- renderUI({
if(!is.null(input$RunFullModel) & global$clicked){
actionButton(inputId= "RunFullModel", label =icon("tree-deciduous", lib = "glyphicon"),
style = "color: white;
background-color: #35e51d;
position: relative;
left: 3%;
height: 35px;
width: 35px;
text-align:center;
text-indent: -2px;
border-radius: 6px;
border-width: 2px")
}else{
actionButton(inputId= "RunFullModel", label =icon("tree-deciduous", lib = "glyphicon"))
}
})
}
)

Leaflet Legend Items Are Not Displayed (Aligned) Correctly in Shiny

I am rendering some leaflet maps in my shiny app and the problem is that the legend of the map is not displayed correctly and legend items are aligned very weirdly (image 2). I create the same map in R studio and in the Rstudio Viewer, legend items alignment is correct (image 1).
I have tried using CSS tags in my shiny code to customize the legend, but nothing works.
Here is sample code to show how I am rendering leaflet plot (and also the CSS tags examples I've tried). I dont know why the items are displayed like this. I would really appreciate your help on this.
...
tabPanel("plot",
tagList(
tags$head(
tags$style(
".leaflet .legend {width:200px; text-align: left;}",
".leaflet .legend i{float: left;}",
".leaflet .legend label{float:left; text-align: left;}"
)
)
),
leafletOutput("leaflet_plot", width = 800, height = 550)
)
...
# code to create leaflet
output$leaflet_plot <- renderLeaflet({
pal <- c("#F1F1F1", brewer.pal(5, "YlOrBr"))
opts <- providerTileOptions(opacity = 0)
map <- leaflet(shape_file) %>% addProviderTiles("CartoDB.PositronNoLabels", options = opts)
map <- map %>% addPolygons(fillColor = ~colorFactor(pal, shape_file$var)(var)
map <- map %>% addLegend("bottomleft", title = "Employment/Acre", pal = colorFactor(pal, NULL), values = ~var)
map
})
This may happen if the zoom level of the browser is more than 100%.
Look at this duplicate post that has a reproducible example.

Resources