Ich möchte auf die akzeptierte Antwort auf diese Frage eingehen .
Ich möchte die minimal glänzende App unten (extrahiert aus der akzeptierten Antwort) mit den folgenden Funktionen verbessern:
- 1) Zeichnen Sie das Rechteck + eine Textbeschriftung . Das Label stammt von R (
input$foo
), z. B. aus einem Dropdown. Um Randfälle zu vermeiden, in denen die Beschriftungen außerhalb der Bilder liegen, sollten Beschriftungen innerhalb ihrer Rechtecke platziert werden. - 2) Verwenden Sie je nach Beschriftung eine andere Farbe für die Rechtecke und ihre Beschriftungen
- 3) Fähigkeit des Benutzers, ein Rechteck durch Doppelklicken zu löschen . Bei mehreren Übereinstimmungen (Überlappung, verschachtelt) sollte das Rechteck mit der kleinsten Fläche gelöscht werden.
Brownie-Punkte für 1): Das Dropdown-Menü könnte wie hier neben dem Cursor angezeigt werden (Code hier ). Wenn möglich, sollte die Dropdown-Liste von server.R übergeben und nicht fest / fest codiert werden. Der Grund ist, dass abhängig von einigen Benutzereingaben eine andere Dropdown-Liste angezeigt werden kann. Zum Beispiel könnten wir ein Dropdown für Früchte c('banana','pineapple','grapefruit')
, ein Dropdown für Tiere c('raccoon','dog','cat')
usw. haben.
# 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
quelle
quelle
Antworten:
Diese Lösung verwendet den bbox_annotator von kyamagu und basiert auf demo.html. Ich kenne JS nicht, also ist es nicht das Schönste. Einschränkungen sind:
ui.R.
server.R
www / bbox_annotation.js
quelle