Me gustaría dar más detalles sobre la respuesta aceptada a esta pregunta .
Estoy buscando mejorar la aplicación brillante mínima a continuación (extraída de la respuesta aceptada) con las siguientes características:
- 1) dibuja el rectángulo + una etiqueta de texto . La etiqueta proviene de R ( 
input$foo), por ejemplo, de un menú desplegable. Para evitar los casos de borde donde las etiquetas caen fuera de las imágenes, las etiquetas deben colocarse dentro de sus rectángulos. - 2) use un color diferente para los rectángulos y sus etiquetas dependiendo de la etiqueta
 - 3) capacidad para que el usuario elimine un rectángulo haciendo doble clic dentro de él . En el caso de múltiples coincidencias (superposición, anidadas), el rectángulo con el área más pequeña debe eliminarse.
 
Brownie señala 1): el menú desplegable podría aparecer al lado del cursor como se hace aquí (código aquí ). Si es posible, la lista desplegable se debe pasar desde server.R y no se debe corregir / codificar. La razón es que dependiendo de alguna entrada del usuario, se podría mostrar un menú desplegable diferente. Por ejemplo, podríamos tener un menú desplegable para frutas c('banana','pineapple','grapefruit'), un menú desplegable para animales c('raccoon','dog','cat'), etc.
# JS and CSS modified from: https://stackoverflow.com/a/17409472/8099834
css <- "
    #canvas {
        width:2000px;
        height:2000px;
        border: 10px solid transparent;
    }
    .rectangle {
        border: 5px solid #FFFF00;
        position: absolute;
    }
"
js <- 
"function initDraw(canvas) {
    var mouse = {
        x: 0,
        y: 0,
        startX: 0,
        startY: 0
    };
    function setMousePosition(e) {
        var ev = e || window.event; //Moz || IE
        if (ev.pageX) { //Moz
            mouse.x = ev.pageX + window.pageXOffset;
            mouse.y = ev.pageY + window.pageYOffset;
        } else if (ev.clientX) { //IE
            mouse.x = ev.clientX + document.body.scrollLeft;
            mouse.y = ev.clientY + document.body.scrollTop;
        }
    };
    var element = null;    
    canvas.onmousemove = function (e) {
        setMousePosition(e);
        if (element !== null) {
            element.style.width = Math.abs(mouse.x - mouse.startX) + 'px';
            element.style.height = Math.abs(mouse.y - mouse.startY) + 'px';
            element.style.left = (mouse.x - mouse.startX < 0) ? mouse.x + 'px' : mouse.startX + 'px';
            element.style.top = (mouse.y - mouse.startY < 0) ? mouse.y + 'px' : mouse.startY + 'px';
        }
    }
    canvas.onclick = function (e) {
        if (element !== null) {
           var coord = {
               left: element.style.left,
               top: element.style.top,
               width: element.style.width,
               height: element.style.height
            };
            Shiny.onInputChange('rectCoord', coord);
            element = null;
            canvas.style.cursor = \"default\";
        } else {
            mouse.startX = mouse.x;
            mouse.startY = mouse.y;
            element = document.createElement('div');
            element.className = 'rectangle'
            element.style.left = mouse.x + 'px';
            element.style.top = mouse.y + 'px';
            canvas.appendChild(element);
            canvas.style.cursor = \"crosshair\";
        }
    }
};
$(document).on('shiny:sessioninitialized', function(event) {
    initDraw(document.getElementById('canvas'));
});
"
library(shiny)
ui <- fluidPage(
  tags$head(
      tags$style(css),
      tags$script(HTML(js))
  ),
  fluidRow(
      column(width = 6, 
             # inline is necessary
             # ...otherwise we can draw rectangles over entire fluidRow
             uiOutput("canvas", inline = TRUE)),
      column(
          width = 6,
          verbatimTextOutput("rectCoordOutput")
          )
  )
)
server <- function(input, output, session) {
    output$canvas <- renderUI({
        tags$img(src = "https://www.r-project.org/logo/Rlogo.png")
    })
    output$rectCoordOutput <- renderPrint({
        input$rectCoord
    })
}
shinyApp(ui, server)
                
                    
                        javascript
                                r
                                browser
                                shiny
                                
                    
                    
                        Antoine
fuente
                
                fuente

Respuestas:
Esta solución utiliza bbox_annotator de kyamagu y se basa en demo.html. No estoy familiarizado con JS, por lo que no es el más bonito. Las limitaciones son:
ui.R
servidor.R
www / bbox_annotation.js
fuente