I am developing a shiny app to allow users to create a curve by moving points ( actually circle shapes) on a plotly scatterplot. The app updates a spline as the points are moved. I need to put some vertical lines ( and possibly rectangles on the plot "background" however these shapes should be fixed, while the circles need to be editable by dragging.
I can only get all the shapes as draggable ( by incuding "config(edits = list(shapePosition = TRUE))" in the plotly pipe.
If I do not incude this line ( but incude editable=TRUE for circles and editable = false for GSLines) then nothing is draggable how do I make it so that just Circles are draggable?
Alternatively is there another way ( other than shapes) to incude fixed vertical guidelines in the plot background?
Thanks
The code was based on add shiny example of dragging markers (for interactive lm) · plotly/plotly.R@eb12338 · GitHub
library(plotly)
library(purrr)
library(shiny)
myCircle<- function(x = 0,y=0,fillcolor = "blue",linecolor ="transparent"){
list(
type = "circle",
xanchor = x,
yanchor = y,
# give each circle a 2 pixel diameter
x0 = -4,
x1 = 4,
y0 = -4,
y1 = 4,
xsizemode = "pixel",
ysizemode = "pixel",
# other visual properties
fillcolor = fillcolor,
line = list(color = linecolor),
editable=TRUE
)
}
GSx<-c(2,10,20)
myline <- function(x = 0, color = "red") {
list(
type = "line",
y0 = 0,
y1 = 1,
yref = "paper",
x0 = x,
x1 = x,
line = list(color = color, dash = "dot"),
editable=FALSE
)
}
Lines = map2(GSx,"red",myline)
ui <- fluidPage(h3("Drag blue dots to change curve and TSF values"),
plotlyOutput("p")
)
server <- function(input, output, session) {
rv <- reactiveValues(x = c(0, 5, 10, 50, 400),
y = c(1, 1, 1, 1, 1))
observeEvent(rv$x | rv$y, {
rv$mySpline <- as.data.frame(spline(
rv$x,
rv$y,
xmin = 0,
xmax = 400,
n = 401
)) %>%
mutate(y = ifelse(y < 0, 0, y)) #restrict Y to values >=0
output$p <- renderPlotly({
# creates a list of circle shapes from x/y data
Circles <- pmap(
list(
rv$x,
rv$y,
"blue",
"transparent"),
myCircle
)
# plot the shapes and fitted line
plot_ly() %>% add_lines(
x = ~ rv$mySpline$x,
y = ~ rv$mySpline$y,
line = list(color = "black")
) %>%
layout(
shapes = c(Circles,Lines),
xaxis = list(title = "Years Since Fire",
range = c(0, 400)),
yaxis = list(title = "Estimated abundance",
range = c(0, 1.5 * (
max(rv$mySpline$y)
)))
) %>%
config(edits = list(shapePosition = TRUE))
})
})
# update x/y reactive values in response to changes in shape anchors
observe({
ed <- event_data("plotly_relayout")
shape_anchors <<- ed[grepl("^shapes.*anchor$", names(ed))]
if (length(shape_anchors) != 2) {
return()
}
row_index <-
unique(readr::parse_number(names(shape_anchors)) + 1)
pts <- as.numeric(shape_anchors)
rv$x[row_index] <-
ifelse(pts[1] > 400, 400, ifelse(pts[1] < 0, 0, pts[1]))
rv$y[row_index] <- ifelse(pts[2] < 0, 0, pts[2])
xx <<- rv$x
yy <<- rv$y
})
}
shinyApp(ui, server)