这个问题是我previous question个问题得到回答的后续问题.
目标
在使用嵌套模块的同时,在shiny 的应用程序中实现手写到文本的转换.
这很管用
有三个相关文件:
- 手写_for_shiny2.js(放在
www
文件夹中) - Mod_handWriting.R(放在
R
文件夹中;这是一个利用js函数的模块) - App.R(放置在应用程序主文件夹中)
Run app.R
显示了一个画布,您可以在其中用手写笔书写,当单击"Send"按钮时,它会转换为文本.还有undo撤消、重做和清除画布按钮.
这不管用
然后,我引入了另一个利用模块mod_handwriting.R
的模块(mod_simple.R
).然后我创建了另一个名为app2.R
的应用程序文件,在其中我使用了mod_simple.R
.但这一次,按钮不起作用.不过,我还是可以在画布上写字.
代码
Here is all the code:
handwriting_for_shiny2.js
$(document).ready(function() {
var handwritingCanvas = {};
Shiny.addCustomMessageHandler("initialize", function(id) {
var canvas = document.getElementById(id + '-handwritingCanvas');
handwritingCanvas[id] = new handwriting.Canvas(canvas, 3);
// Enable undo and redo
handwritingCanvas[id].set_Undo_Redo(true, true);
console.log("This is initialize function");
});
Shiny.addCustomMessageHandler("clearCanvas", function(id) {
handwritingCanvas[id].erase();
console.log("This is clearCanvas function");
});
Shiny.addCustomMessageHandler("undoCanvas", function(id) {
handwritingCanvas[id].undo();
});
Shiny.addCustomMessageHandler("redoCanvas", function(id) {
handwritingCanvas[id].redo();
});
Shiny.addCustomMessageHandler("sendCanvas", function(id) {
var trace = handwritingCanvas[id].trace;
var options = {
language: 'en',
numOfReturn: 1
};
var callback = function(result, err) {
if (err) {
console.error(err);
} else {
Shiny.setInputValue(id + '-recognized_text', result[0]);
}
};
handwriting.recognize(trace, options, callback);
});
});
mod_handwriting.R个
handwritingUI <- function(id) {
ns <- NS(id)
fluidRow(
column(
width = 4,
actionButton(ns("clear_canvas"), "Clear Canvas"),
actionButton(ns("undo"), "Undo"),
actionButton(ns("redo"), "Redo"),
actionButton(ns("send"), "Send"),
textAreaInput(ns("manual_text"), "Enter Text", value = ""),
tags$canvas(id = ns("handwritingCanvas"), width = "400px", height = "200px")
)
)
}
handwritingServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
observe({
session$sendCustomMessage("initialize", message = id)
})
observeEvent(input$clear_canvas, {
session$sendCustomMessage("clearCanvas", message = id)
})
observeEvent(input$send, {
session$sendCustomMessage("sendCanvas", message = id)
})
observeEvent(input$undo, {
print("Undo button clicked") # Diagnostic output
session$sendCustomMessage("undoCanvas", message = id)
})
observeEvent(input$redo, {
session$sendCustomMessage("redoCanvas", message = id)
})
observeEvent(input$recognized_text, {
if (!is.null(input$recognized_text)) {
updateTextAreaInput(session, "manual_text", value = input$recognized_text)
}
})
observe({
session$sendCustomMessage("initCanvas", message = NULL)
})
}
)
}
app.R个
library(shiny)
ui <- fluidPage(
tags$head(
tags$script(src = "handwriting.js"),
tags$script(src = "handwriting.canvas.js"),
tags$script(src = "handwriting_for_shiny2.js"),
tags$style(HTML("
#handwritingCanvas {
border: 1px solid #000;
margin-top: 10px;
margin-bottom: 10px;
}
"))
),
titlePanel("Handwriting Recognition"),
handwritingUI("module1")
)
server <- function(input, output, session) {
handwritingServer("module1")
}
shinyApp(ui, server)
mod_simple.R
mod_simple_ui <- function(id) {
ns <- NS(id)
tagList(
handwritingUI(ns("foo"))
)
}
mod_simple_server <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
handwritingServer(ns("foo"))
}
)
}
app2.R个
library(shiny)
ui <- fluidPage(
tags$head(
tags$script(src = "handwriting.js"),
tags$script(src = "handwriting.canvas.js"),
tags$script(src = "handwriting_for_shiny2.js"),
tags$style(HTML("
#handwritingCanvas {
border: 1px solid #000;
margin-top: 10px;
margin-bottom: 10px;
}
"))
),
titlePanel("Handwriting Recognition"),
mod_simple_ui("module1")
)
server <- function(input, output, session) {
mod_simple_server("module1")
}
shinyApp(ui, server)
调试JS代码:
我已经在JS代码中放置了console.log
条语句.我看到两个 fingerprint 都是app.R
,但只有This is initialize function
和app2.R
.不知何故,clearCanvas
功能没有被触发(其他按钮功能也是如此).这似乎是一个名称空间问题.如果有任何帮助,我将不胜感激.
编辑
通过删除服务器部件中的ns
更改了mod_simple.R
:
mod_simple_ui <- function(id) {
ns <- NS(id)
tagList(
handwritingUI(ns("foo"))
)
}
mod_simple_server <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
handwritingServer("foo")
}
)
}
但随着这一变化,我失go 了在画布内写作的能力.此外,控制台显示以下错误:
shinyapp.ts:442 TypeError: Cannot read properties of null (reading 'getContext')
at new handwriting.Canvas (handwriting.canvas.js:19:24)
at e.<anonymous> (handwriting_for_shiny2.js:6:29)
at e.<anonymous> (shinyapp.ts:866:40)
at m (shinyapp.ts:5:1357)
at Generator.<anonymous> (shinyapp.ts:5:4174)
at Generator.next (shinyapp.ts:5:2208)
at f0 (shinyapp.ts:6:99)
at s (shinyapp.ts:7:194)
at shinyapp.ts:7:364
at new Promise (<anonymous>)
(anonymous) @ shinyapp.ts:442
shinyapp.ts:442 TypeError: Cannot read properties of undefined (reading 'erase')
at e.<anonymous> (handwriting_for_shiny2.js:14:27)
at e.<anonymous> (shinyapp.ts:866:40)
at m (shinyapp.ts:5:1357)
at Generator.<anonymous> (shinyapp.ts:5:4174)
at Generator.next (shinyapp.ts:5:2208)
at f0 (shinyapp.ts:6:99)
at s (shinyapp.ts:7:194)
at shinyapp.ts:7:364
at new Promise (<anonymous>)
at e.<anonymous> (shinyapp.ts:7:97)
(anonymous) @ shinyapp.ts:442
m @ shinyapp.ts:5
(anonymous) @ shinyapp.ts:5
(anonymous) @ shinyapp.ts:5
f0 @ shinyapp.ts:6
c @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7
Promise.then (async)
f0 @ shinyapp.ts:6
s @ shinyapp.ts:7