This is a follow-up question to this Color an area with a sliderInput in a shiny app
Suppose I have this image:
How could I apply this solution by @ismirsehregal to this picture. I think I have to put the x and y from the esophagus to the code, but I don't know how to get the x and y of the esophagues (green in the picture):
Code from Color an area with a sliderInput in a shiny app
library(shiny)
library(plotly)
library(shinyWidgets)
DF <- data.frame(
x = c(cos(seq(0.01, 10, 0.01)) * 1000:1 + 1000, cos(seq(0.01, 10, 0.01)) * 1000:1 + 1500),
y = rep(1:1000, 2),
id = c(rep("trace_1", 1000), rep("trace_2", 1000))
)
ui <- fluidPage(
br(),
column(
2,
noUiSliderInput(
inputId = "noui2",
label = "Slider vertical:",
min = 0,
max = 1000,
step = 50,
value = c(100, 400),
margin = 100,
orientation = "vertical",
direction = c("rtl"),
width = "100px",
height = "350px"
)
),
column(4, plotlyOutput("plot")),
verbatimTextOutput(outputId = "res2")
)
server <- function(input, output, session) {
output$res2 <- renderPrint(input$noui2)
plotDF <- reactive({
plotDF <- DF[DF$y %in% input$noui2[1]:input$noui2[2], ]
plotDF$id <- paste0("filtered_", plotDF$id)
plotDF
})
output$plot <- renderPlotly({
fig <- plot_ly(
rbind(DF, plotDF()),
x = ~ x,
y = ~ y,
split = ~ id,
type = "scatter",
mode = "lines",
color = I("black"),
fillcolor = 'red',
showlegend = FALSE
) |> style(fill = 'tonexty', traces = 2)
})
}
shinyApp(ui, server)
The following approach doesn't meet the title of your question, but it shows the procedure I mentioned in your previous post.
You will need to save a modified png file (transparent esophagus - edited with gimp's "fuzzy select tool") in your apps www
folder for this to work (please find it below).
I'm now using plotlyProxyInvoke
to update the data without re-rendering the plot:
library(shiny)
library(plotly)
library(shinyWidgets)
slider_min <- 0
slider_max <- 45
lower_slider_value <- 5
upper_slider_value <- 18
x_position_trace_1 <- 40
x_position_trace_2 <- 50
DF <- data.frame(
x = c(rep(x_position_trace_1, 2), rep(x_position_trace_2, 2)),
y = rep(c(lower_slider_value, upper_slider_value), 2),
id = c(rep("trace_1", 2), rep("trace_2", 2))
)
ui <- fluidPage(
br(),
column(
2,
noUiSliderInput(
inputId = "noui2",
label = "Slider vertical:",
min = slider_min,
max = slider_max,
step = 1L,
value = c(lower_slider_value, upper_slider_value),
margin = 1,
orientation = "vertical",
width = "100px",
height = "350px"
)
),
column(4, plotlyOutput("myPlot", height = "800px")),
verbatimTextOutput(outputId = "res2")
)
server <- function(input, output, session) {
output$res2 <- renderPrint(input$noui2)
output$myPlot <- renderPlotly({
fig <- plot_ly(
DF,
x = ~ x,
y = ~ y,
split = ~ id,
type = "scatter",
mode = "lines",
color = I("white"),
fillcolor = 'red',
showlegend = FALSE
) |> layout(
images = list(
list(
source = "/esophagus.png",
xref = "x",
yref = "y",
x = 0,
y = -16,
sizex = 93,
sizey = 93,
sizing = "stretch",
opacity = 1,
layer = "above"
)
),
plot_bgcolor = "rgba(0, 0, 0, 0)",
paper_bgcolor = "rgba(0, 0, 0, 0)",
xaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff',
range = list(0, 100)),
yaxis = list(
zerolinecolor = '#ffff',
zerolinewidth = 2,
gridcolor = 'ffff',
range = list(80, -20)
# or autorange = "reversed"
)
) |> style(fill = 'tonexty', traces = 2)
})
myPlotProxy <- plotlyProxy("myPlot", session)
observe({
plotlyProxyInvoke(myPlotProxy, "restyle", list(x = list(rep(x_position_trace_1, 2), rep(x_position_trace_2, 2)), y = list(input$noui2, input$noui2)), list(0, 1))
})
}
shinyApp(ui, server)
Image for the www
folder - save as "esophagus.png".
To visualize the transparent area (grey) open the image in a new browser tab (chrome):
Edit: Here is another lightweight approach without using {plotly}.
This isn't perfectly aligned yet and it might make sense to work wit %
instead of px
, however it shows the principle:
We can simply provide the esophagus image with a red background image and modify the css properties background-size
and background-position-y
:
library(shiny)
library(shinyjs)
library(shinyWidgets)
ui <- fluidPage(
useShinyjs(),
br(),
column(
2,
noUiSliderInput(
inputId = "noui2",
label = "Slider vertical:",
min = 0,
max = 1000,
step = 50,
value = c(100, 400),
margin = 100,
orientation = "vertical",
direction = c("rtl"),
width = "100px",
height = "350px"
)
),
column(
4,
tags$img(
id = "esophagus",
height = 1000,
width = "100%",
src = "/esophagus.png",
style = "background-image: url(red_background.png); background-repeat: no-repeat; background-size: 100% 30%; background-position-y: 40%;"
)
),
verbatimTextOutput(outputId = "res2")
)
server <- function(input, output, session) {
output$res2 <- renderPrint(input$noui2)
observeEvent(input$noui2, {
runjs(paste0('$("#esophagus").css("background-size", "100% ', input$noui2[2] - input$noui2[1], 'px");'))
runjs(paste0('$("#esophagus").css("background-position-y", "', 1000 - input$noui2[2], 'px");'))
})
}
shinyApp(ui, server)
Save as "red_background.png" in your www
folder: