我想向我 Shiny 的应用程序中的中央 graphviz 节点添加一个功能(弹出窗口或其他功能?),当通过鼠标单击选择时,它们会显示信息(例如 center_nodes 文件中的信息列) 。鉴于这些节点有一个工具提示属性,我认为/希望计算机必须“看到”它们,但我还没有找到连接这两个节点并建立这种行为的方法......
我探索了各种方法(例如reactR,html标签,hover.css,shinyBS,d3,pipeR,XML,htmltools),但认为它一定可以使用css或htmlwidgets,但我对这段代码的了解能力有限,目前还没有找到解决办法。我觉得对于熟悉这种类型编码的人来说它很简单......
这是一个使用 DiagrammeR
和 grViz
的示例 Shiny 应用程序:
library(DiagrammeR)
library(shiny)
ui = shinyUI(fluidPage(grVizOutput('graphV')))
server = function(input, output) {
output$graphV <- renderGrViz({
grViz( "digraph test{
A[tooltip='A word'];
B[tooltip='Another word'];
A -> B;}" )
})}
shinyApp(ui = ui, server = server)
希望的结果是我可以通过单击选择一个节点,然后将显示与该节点相关的信息。通过工具提示功能,我可以滚动节点并显示信息,但对单击的响应在美观上会更具吸引力。甚至能够更改工具提示的外观也将是对当前工具提示的改进。
非常感谢任何帮助!
最佳答案
这里是关于如何根据被单击的元素添加 html 元素的草案。也许你可以在你想要放置它们的地方详细说明一下,或者如果你也可以添加其他 Shiny 的元素(会更容易)。
下面代码的想法是添加一个 onclick 监听器。捷径是用shinyjs
来实现它。元素的标识符似乎是 node1
、node2
等。
然后有多个选项。将该信息返回给“R/Shiny”,并通过 Shiny.OnInputChanged(...)
添加 Shiny 元素或通过 javascript 附加 html 元素。
使用 Shiny.OnInputChanged(...)
更容易,所以我尝试让第二个也能工作。下面给出一个例子。
在图表中添加新的 html 元素并将它们放在图表前面并不简单。人们可以通过校准 css 以将其显示在前面进行实验 (style="z-index: -1"
),但也许进一步指定最佳解决方案是一个好点。
(为了完整起见,添加的元素当然也可以删除,这样一次只显示一个“工具提示”,...)
可重现的示例:
library(DiagrammeR)
library(shiny)
library(shinyjs)
texts <- c("Great div for A", "Even better div for B")
jsCode <- paste0("
elem = document.getElementById('graphV');
var node = document.createElement('div');
var textnode = document.createTextNode('", texts,"');
node.appendChild(textnode);
elem.appendChild(node);
")
ui = shinyUI(
fluidPage(
useShinyjs(),
grVizOutput('graphV')
)
)
server = function(input, output, session) {
observe({
for(nodeNr in 1:length(jsCode)){
local({
jsToAdd <- jsCode[nodeNr]
shinyjs::onclick(paste0("node", nodeNr), runjs(jsToAdd))
})
}
})
output$graphV <- renderGrViz({
grViz( "digraph test{
A[tooltip='A word'];
B[tooltip='Another word'];
A -> B;}" )
})}
shinyApp(ui = ui, server = server)
尝试让工具提示覆盖图表失败:
library(DiagrammeR)
library(shiny)
library(shinyjs)
texts <- c("Great div for A", "Even better div for B")
jsCode <- paste0("
elem = document.getElementById('node1');
var node = document.createElement('div');
var textnode = document.createTextNode('", texts,"');
node.appendChild(textnode);
node.classList.add('mystyle');
elem.appendChild(node);
")
ui = shinyUI(
fluidPage(
useShinyjs(),
tags$style("
.mystyle {
z-index: 100 !important;
background-color: coral;
font-size: 25px;
}
#node1 {
width: 50px;
z-index: unset !important;
background-color: blue;
}
"),
grVizOutput('graphV')
)
)
server = function(input, output, session) {
observe({
for(nodeNr in 1:length(jsCode)){
local({
jsToAdd <- jsCode[nodeNr]
shinyjs::onclick(paste0("node", nodeNr), runjs(jsToAdd))
})
}
})
output$graphV <- renderGrViz({
grViz( "digraph test{
A[tooltip='A word'];
B[tooltip='Another word'];
A -> B;}" )
})}
shinyApp(ui = ui, server = server)
编辑评论中的问题:
例如,如果您有一个 40 个节点的图表,是否有办法自动将节点 ID 链接到节点描述(在上面的情况下为“A 的 Great div”)?或者我只需要按照 graphviz 代码中列出的节点顺序对文本文件进行排序?
正确。在diagrammeR代码中,它似乎只是向上计数id:“node1,node2,node3,...)。
所以我只是在 Shiny 中做同样的事情:
for(nodeNr in 1:length(jsCode)){
local({
jsToAdd <- jsCode[nodeNr]
shinyjs::onclick(paste0("node", nodeNr), runjs(jsToAdd))
})
}
如您所见,对于节点号 paste0("node", nodeNr)
,将为点击事件分配 javascript 代码 jsCode[nodeNr]
。
并且 jsCode[nodeNr]
将包含 texts[nodeNr]
。 (请注意,jsCode
将是根据 texts
长度的字符串向量。
关于r - 是否可以在 Shiny 的应用程序(renderGrViz)中选择一个graphviz节点,然后链接到其他信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57601875/