图像未使用 Shiny renderImage 在 Canvas 内渲染
Image not rendering inside Canvas using Shiny renderImage
我正在尝试在 Shiny 应用程序中以交互方式使用 Fabric.js。 Shiny 应该渲染图像,然后用户将通过 Fabric 修改它。然后,Shiny 将该图像读回服务器并进一步处理它。但是,我现在无法通过第一步!
在下面的代码中,plot/png 显示在 canvas 下方,但不在其内部。我在 javascript 中引用图像 ID 的方式有误吗?
可能是因为 renderImage 将图像放在 div?
代码如下:
library(shiny)
js <- "
$(document).ready(function () {
var canvas = new fabric.Canvas('drawarea');
var imgElement = document.getElementById('myimage');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 0,
opacity: 0.75,
width:300,
height:300
});
canvas.add(imgInstance);
});
"
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
tags$head(tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js", type="text/javascript")),
tags$head(
tags$style(HTML("
canvas {
border: 1px solid #999;
}
myimage{display:none;}
"))
),
titlePanel("Fabric Demo"),
sidebarLayout(
sidebarPanel(
h4("Side")
),
mainPanel(
HTML('
<canvas width="800" height="800" id="drawarea" style="border: 1px solid red;float: right"> </canvas>
'),
plotOutput("div.for.image")
)
)
)
server <- function(input, output, session) {
output$div.for.image <- renderImage({
outfile <- tempfile(fileext='.png')
# Generate a png
png(outfile, width=400, height=400)
hist(rnorm(20))
dev.off()
# Return a list
list(src = outfile,
alt = "This is alternate text",
id = "myimage")
}, deleteFile = TRUE)
}
shinyApp(ui=ui,server=server)
您必须在 Shiny 插入图像后触发 JavaScript 代码。现在,您将在文档准备就绪后立即重新启动代码。
我将使用 shinyjs
来完成此任务并使用 runjs
和 delay
函数,以等待包含图像的列表返回并在 [=26= 中可见].
如果你想隐藏 Shiny 渲染的图像,你需要在 css 中添加 #(如 #myimage
)
完整代码:
library(shiny)
library(shinyjs)
js <- "
$(document).ready(function () {
var canvas = new fabric.Canvas('drawarea');
var imgElement = document.getElementById('myimage');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 0,
opacity: 0.75,
width:300,
height:300
});
canvas.add(imgInstance);
});
"
# ui #########
ui <- fluidPage(
useShinyjs(),
tags$head(tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js", type="text/javascript")),
tags$head(
tags$style(HTML("canvas {border: 1px solid #999;}
#myimage{display:none;}"))
),
titlePanel("Fabric Demo"),
sidebarLayout(
sidebarPanel(
h4("Side")
),
mainPanel(
HTML('<canvas width="800" height="800" id="drawarea" style="border: 1px solid red;float: right"></canvas>'),
plotOutput("div.for.image")
)
)
)
## server #######
server <- function(input, output, session) {
output$div.for.image <- renderImage({
outfile <- tempfile(fileext='.png')
# Generate a png
png(outfile, width=400, height=400)
hist(rnorm(20))
dev.off()
delay(200, runjs(HTML(js)))
# Return a list
list(src = outfile,
alt = "This is alternate text",
id = "myimage")
}, deleteFile = TRUE)
}
shinyApp(ui=ui,server=server)
您可以使用 shiny:value
JavaScript 事件,该事件在呈现输出时触发。
library(shiny)
js <- "
$(document).on('shiny:value', function(evt) {
if(evt.name === 'divForImage') {
setTimeout(function(){
var canvas = new fabric.Canvas('drawarea');
var imgElement = document.getElementById('myimage');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 0,
opacity: 0.75,
width: 300,
height: 300
});
canvas.add(imgInstance);
}, 0);
}
});
"
# ui #########
ui <- fluidPage(
tags$head(
tags$script(
src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"
),
tags$script(HTML(js)),
tags$style(HTML(
"canvas {border: 1px solid #999;}
#myimage{display:none;}"))
),
titlePanel("Fabric Demo"),
sidebarLayout(
sidebarPanel(
h4("Side")
),
mainPanel(
tags$canvas(
width="800", height="800", id="drawarea", style="border: 1px solid red; float: right;"
),
imageOutput("divForImage")
)
)
)
## server #######
server <- function(input, output, session) {
output[["divForImage"]] <- renderImage({
outfile <- tempfile(fileext='.png')
# Generate a png
png(outfile, width=400, height=400)
hist(rnorm(20))
dev.off()
# Return a list
list(src = outfile,
alt = "This is alternate text",
id = "myimage")
}, deleteFile = TRUE)
}
shinyApp(ui=ui, server=server)
注意:不要在 ID 中使用句点,这会导致一些问题。
我正在尝试在 Shiny 应用程序中以交互方式使用 Fabric.js。 Shiny 应该渲染图像,然后用户将通过 Fabric 修改它。然后,Shiny 将该图像读回服务器并进一步处理它。但是,我现在无法通过第一步!
在下面的代码中,plot/png 显示在 canvas 下方,但不在其内部。我在 javascript 中引用图像 ID 的方式有误吗?
可能是因为 renderImage 将图像放在 div?
代码如下:
library(shiny)
js <- "
$(document).ready(function () {
var canvas = new fabric.Canvas('drawarea');
var imgElement = document.getElementById('myimage');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 0,
opacity: 0.75,
width:300,
height:300
});
canvas.add(imgInstance);
});
"
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
tags$head(tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js", type="text/javascript")),
tags$head(
tags$style(HTML("
canvas {
border: 1px solid #999;
}
myimage{display:none;}
"))
),
titlePanel("Fabric Demo"),
sidebarLayout(
sidebarPanel(
h4("Side")
),
mainPanel(
HTML('
<canvas width="800" height="800" id="drawarea" style="border: 1px solid red;float: right"> </canvas>
'),
plotOutput("div.for.image")
)
)
)
server <- function(input, output, session) {
output$div.for.image <- renderImage({
outfile <- tempfile(fileext='.png')
# Generate a png
png(outfile, width=400, height=400)
hist(rnorm(20))
dev.off()
# Return a list
list(src = outfile,
alt = "This is alternate text",
id = "myimage")
}, deleteFile = TRUE)
}
shinyApp(ui=ui,server=server)
您必须在 Shiny 插入图像后触发 JavaScript 代码。现在,您将在文档准备就绪后立即重新启动代码。
我将使用 shinyjs
来完成此任务并使用 runjs
和 delay
函数,以等待包含图像的列表返回并在 [=26= 中可见].
如果你想隐藏 Shiny 渲染的图像,你需要在 css 中添加 #(如 #myimage
)
完整代码:
library(shiny)
library(shinyjs)
js <- "
$(document).ready(function () {
var canvas = new fabric.Canvas('drawarea');
var imgElement = document.getElementById('myimage');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 0,
opacity: 0.75,
width:300,
height:300
});
canvas.add(imgInstance);
});
"
# ui #########
ui <- fluidPage(
useShinyjs(),
tags$head(tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js", type="text/javascript")),
tags$head(
tags$style(HTML("canvas {border: 1px solid #999;}
#myimage{display:none;}"))
),
titlePanel("Fabric Demo"),
sidebarLayout(
sidebarPanel(
h4("Side")
),
mainPanel(
HTML('<canvas width="800" height="800" id="drawarea" style="border: 1px solid red;float: right"></canvas>'),
plotOutput("div.for.image")
)
)
)
## server #######
server <- function(input, output, session) {
output$div.for.image <- renderImage({
outfile <- tempfile(fileext='.png')
# Generate a png
png(outfile, width=400, height=400)
hist(rnorm(20))
dev.off()
delay(200, runjs(HTML(js)))
# Return a list
list(src = outfile,
alt = "This is alternate text",
id = "myimage")
}, deleteFile = TRUE)
}
shinyApp(ui=ui,server=server)
您可以使用 shiny:value
JavaScript 事件,该事件在呈现输出时触发。
library(shiny)
js <- "
$(document).on('shiny:value', function(evt) {
if(evt.name === 'divForImage') {
setTimeout(function(){
var canvas = new fabric.Canvas('drawarea');
var imgElement = document.getElementById('myimage');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 0,
opacity: 0.75,
width: 300,
height: 300
});
canvas.add(imgInstance);
}, 0);
}
});
"
# ui #########
ui <- fluidPage(
tags$head(
tags$script(
src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"
),
tags$script(HTML(js)),
tags$style(HTML(
"canvas {border: 1px solid #999;}
#myimage{display:none;}"))
),
titlePanel("Fabric Demo"),
sidebarLayout(
sidebarPanel(
h4("Side")
),
mainPanel(
tags$canvas(
width="800", height="800", id="drawarea", style="border: 1px solid red; float: right;"
),
imageOutput("divForImage")
)
)
)
## server #######
server <- function(input, output, session) {
output[["divForImage"]] <- renderImage({
outfile <- tempfile(fileext='.png')
# Generate a png
png(outfile, width=400, height=400)
hist(rnorm(20))
dev.off()
# Return a list
list(src = outfile,
alt = "This is alternate text",
id = "myimage")
}, deleteFile = TRUE)
}
shinyApp(ui=ui, server=server)
注意:不要在 ID 中使用句点,这会导致一些问题。