Javascript 在图像上绘制矩形的浏览器友好方式
我已经编写了一个闪亮的应用程序,允许用户在图像顶部绘制矩形(下面是一个最小的可复制示例) 我目前的方法的问题是,每次添加一个矩形时,都会创建一个新的图像,并将其写入磁盘,然后进行渲染(发送到用户的浏览器)。这需要相当长的时间,并且在Internet连接缓慢时会变得非常烦人 是否有任何方法可以直接在浏览器中显示图像顶部的矩形,而无需修改服务器端的图像?我唯一需要确保的是浏览器将绘图上的矩形坐标发送回服务器 我正在寻找的一个很好的例子(JavaScript): 我知道JavaScript可以通过小部件嵌入到闪亮的应用程序中,如果没有人提出更简单的解决方案,我会这么做Javascript 在图像上绘制矩形的浏览器友好方式,javascript,image,browser,shiny,draw,Javascript,Image,Browser,Shiny,Draw,我已经编写了一个闪亮的应用程序,允许用户在图像顶部绘制矩形(下面是一个最小的可复制示例) 我目前的方法的问题是,每次添加一个矩形时,都会创建一个新的图像,并将其写入磁盘,然后进行渲染(发送到用户的浏览器)。这需要相当长的时间,并且在Internet连接缓慢时会变得非常烦人 是否有任何方法可以直接在浏览器中显示图像顶部的矩形,而无需修改服务器端的图像?我唯一需要确保的是浏览器将绘图上的矩形坐标发送回服务器 我正在寻找的一个很好的例子(JavaScript): 我知道JavaScript可以通过小部
库(闪亮)
图书馆(png)
图书馆(RCurl)
我的URL=https://raw.githubusercontent.com/Tixierae/deep_learning_NLP/master/CNN_IMDB/cnn_illustration.png'
my_img=readPNG(getURLContent(myurl))
img_height=dim(my_img)[1]
img_width=dim(my_img)[2]
服务器=功能(输入、输出){
观察({
outfile=tempfile(tmpdir='./',fileext='.png')
png(文件名=输出文件,宽度=图像宽度,高度=图像高度)
par(mar=c(0,0,0,0),xaxs='i',yaxs='i')
绘图(NA,xlim=c(0,img_宽度),ylim=c(0,img_高度))
光栅图像(我的图像,0,0,图像宽度,图像高度)
如果(!为.null(输入$image\u笔刷)){
b_in=lappy(输入$image_brush,如.numeric)
如果(!为.null(b_单位为$xmin)){
rect(b_单位为$xmin,img_高度-b_单位为$ymax,b_单位为$xmax,img_高度-b_单位为$ymin,border='green',lwd=5)
}
}
发展主任()
输出$my_image=renderImage({
名单(
src=输出文件,
contentType='image/png',
宽度=img_宽度,
高度=img_高度,
alt=“”
)
},deleteFile=TRUE)
输出$image=renderUI({
imageOutput('my_image',
高度=img_高度,
宽度=img_宽度,
单击='image\u click',
dblclick=dblclickOpts(
id='image_dblclick'
),
hover=hoverOpts(
id='image\u hover'
),
画笔=画笔选项(
id='image\u brush',resetOnNew=TRUE,delayType='debounce',delay=100000
)
)
})
})
}
ui=引导(
uiOutput('图像')
)
shinyApp(用户界面=用户界面,服务器=服务器)
这里有一个完全基于JS的JS选项
#JS和CSS修改自:https://stackoverflow.com/a/17409472/8099834
css太棒了,非常感谢!我很可能会接受你的回答,并将你的赏金奖励给你,我只是再等几个小时,以防万一其他人想要贡献。您是否知道如何通过双击矩形内部来删除矩形?(如果存在多个匹配项,则为最内侧的矩形)。这不是原始问题的一部分,所以如果你不想回答这个问题,我会理解的。事实上,我问了这个后续问题作为一个新的线索:如果你想详细说明你的答案,你可以得到奖励,很高兴这很有帮助:)我不知道如何删除矩形,但我会研究它!谢谢,我希望你能有所贡献!只是想让你知道我已经开始悬赏这个新问题,以防你想插手
# 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)