Firefox 中 sankeyNetwork (NetworkD3) 的微小图输出
Tiny plot output from sankeyNetwork (NetworkD3) in Firefox
根据对象,当使用 networkd3 in shiny 中的 sankeyNetwork()
但在 Chrome 或 RStudio 中没有时,我在 Firefox 中得到了一个非常小的图。
我没有在脚本中包含任何 CSS 或 JS - 下面的代码为我生成了这个结果。
有没有CSS属性我错过了?
我正在使用 R 3.4.1、shiny 1.1.0、networkD3 0.4 和 Firefox 52.9.0。
火狐:
Chrome:
library(shiny)
library(magrittr)
library(shinydashboard)
library(networkD3)
labels = as.character(1:9)
ui <- tagList(
dashboardPage(
dashboardHeader(
title = "appName"
),
##### dasboardSidebar #####
dashboardSidebar(
sidebarMenu(
id = "sidebar",
menuItem("plots",
tabName = "sPlots")
)
),
##### dashboardBody #####
dashboardBody(
tabItems(
##### tab #####
tabItem(
tabName = "sPlots",
tabsetPanel(
tabPanel(
"Sankey plot",
fluidRow(
box(title = "title",
solidHeader = TRUE, collapsible = TRUE, status = "primary",
sankeyNetworkOutput("sankeyHSM1")
)
)
)
)
)
)
)
)
)
server <- function(input, output, session) {
HSM = matrix(rep(c(10000, 700, 10000-700, 200, 500, 50, 20, 10, 2,40,10,10,10,10),4),ncol = 4)
sankeyHSMNetworkFun = function(x,ndx) {
nodes = data.frame("name" = factor(labels, levels = labels),
"group" = as.character(c(1,2,2,3,3,4,4,4,4)))
links = as.data.frame(matrix(byrow=T,ncol=3,c(
0, 1, NA,
0, 2, NA,
1, 3, NA,
1, 4, NA,
3, 5, NA,
3, 6, NA,
3, 7, NA,
3, 8, NA
)))
links[,3] = HSM[2:(nrow(links)+1),] %>% {rowSums(.[,(ndx-1)*2+c(1,2)])}
names(links) = c("source","target","value")
sankeyNetwork(Links = links, Nodes = nodes, Source = "source", Target = "target", Value = "value", NodeID = "name",NodeGroup = "group",
fontSize=12,sinksRight = FALSE)
}
output$sankeyHSM1 = renderSankeyNetwork({
sankeyHSMNetworkFun(values$HSM,1)
})
}
# Run the application
shinyApp(ui = ui, server = server)
----------------编辑--------------------
感谢@CJYetman 指出 onRender()
作为一个可能的解决方案——但是当有两个并排生成的图时,如下面的 MRE 所示,这失败了(注意除了第二个 sankey 图我还有添加了 javascript 代码以在 window 大小发生变化时重新绘制图形,因为绘图似乎不会自动执行)。
library(shiny)
library(magrittr)
library(shinydashboard)
library(networkD3)
library(htmlwidgets)
labels = as.character(1:9)
ui <- tagList(
tags$head(
tags$script('
var dimension = [0, 0];
$(document).on("shiny:connected", function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange("dimension", dimension);
});
$(window).resize(function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange("dimension", dimension);
});
')
),
dashboardPage(
dashboardHeader(
title = "appName"
),
##### dasboardSidebar #####
dashboardSidebar(
sidebarMenu(
id = "sidebar",
menuItem("plots",
tabName = "sPlots")
)
),
##### dashboardBody #####
dashboardBody(
tabItems(
##### tab #####
tabItem(
tabName = "sPlots",
tabsetPanel(
tabPanel(
"Sankey plot",
fluidRow(
box(title = "title",
solidHeader = TRUE, collapsible = TRUE, status = "primary",
sankeyNetworkOutput("sankeyHSM1")
),
box(title = "plot2",
solidHeader = TRUE, collapsible = TRUE, status = "primary",
sankeyNetworkOutput("sankeyHSM2"))
)
)
)
)
)
)
)
)
server <- function(input, output, session) {
HSM = matrix(rep(c(10000, 700, 10000-700, 200, 500, 50, 20, 10, 2,40,10,10,10,10),4),ncol = 4)
sankeyHSMNetworkFun = function(x,ndx) {
nodes = data.frame("name" = factor(labels, levels = labels),
"group" = as.character(c(1,2,2,3,3,4,4,4,4)))
links = as.data.frame(matrix(byrow=T,ncol=3,c(
0, 1, NA,
0, 2, NA,
1, 3, NA,
1, 4, NA,
3, 5, NA,
3, 6, NA,
3, 7, NA,
3, 8, NA
)))
links[,3] = HSM[2:(nrow(links)+1),] %>% {rowSums(.[,(ndx-1)*2+c(1,2)])}
names(links) = c("source","target","value")
sankeyNetwork(Links = links, Nodes = nodes, Source = "source", Target = "target", Value = "value", NodeID = "name",NodeGroup = "group",
fontSize=12,sinksRight = FALSE)
}
output$sankeyHSM1 = renderSankeyNetwork({
req(input$dimension)
sankeyHSMNetworkFun(values$HSM,1) %>%
onRender('document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
})
output$sankeyHSM2 = renderSankeyNetwork({
req(input$dimension)
sankeyHSMNetworkFun(values$HSM,2) %>%
onRender('document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
})
}
# Run the application
shinyApp(ui = ui, server = server)
---------------- 编辑 2 ------------------
上面的第二个问题已解决——根据@CJYetman 在下面的评论使用 document.getElementsByTagName("svg")[1].setAttribute("viewBox","")
引用页面上的第二个 svg 项目,或者通过使用 [=15] 进入对象本身选择它们的第一个 svg 元素=].
这似乎是 Firefox 对 viewbox
svg 属性 的反应不同于其他浏览器的结果。可能值得在此处将其作为问题提交 https://github.com/christophergandrud/networkD3/issues
同时,您可以通过使用 JavaScript 和 htmlwidgets::onRender()
重置 viewbox
属性来解决此问题。这是一个使用示例的最小化版本的示例。 (重置 viewbox
属性可能会产生其他后果)
library(htmlwidgets)
library(networkD3)
library(magrittr)
nodes = data.frame("name" = factor(as.character(1:9)),
"group" = as.character(c(1,2,2,3,3,4,4,4,4)))
links = as.data.frame(matrix(byrow = T, ncol = 3, c(
0, 1, 1400,
0, 2, 18600,
1, 3, 400,
1, 4, 1000,
3, 5, 100,
3, 6, 40,
3, 7, 20,
3, 8, 4
)))
names(links) = c("source","target","value")
sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
NodeGroup = "group", fontSize = 12, sinksRight = FALSE)
htmlwidgets::onRender(sn, 'document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
更新 (2019.10.26)
这可能是一个更安全的移除 viewBox 的实现...
htmlwidgets::onRender(sn, 'function(el) { el.getElementsByTagName("svg")[0].removeAttribute("viewBox") }')
更新 2020.04.02
我目前首选的方法是使用 htmlwidgets::onRender
专门针对传递的 htmlwidget 包含的 SVG,就像这样...
onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
然后可以根据需要专门针对您页面上的尽可能多的 htmlwidgets
执行此操作,例如...
onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
onRender(sn2, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
根据对象,当使用 networkd3 in shiny 中的 sankeyNetwork()
但在 Chrome 或 RStudio 中没有时,我在 Firefox 中得到了一个非常小的图。
我没有在脚本中包含任何 CSS 或 JS - 下面的代码为我生成了这个结果。
有没有CSS属性我错过了?
我正在使用 R 3.4.1、shiny 1.1.0、networkD3 0.4 和 Firefox 52.9.0。
火狐:
Chrome:
library(shiny)
library(magrittr)
library(shinydashboard)
library(networkD3)
labels = as.character(1:9)
ui <- tagList(
dashboardPage(
dashboardHeader(
title = "appName"
),
##### dasboardSidebar #####
dashboardSidebar(
sidebarMenu(
id = "sidebar",
menuItem("plots",
tabName = "sPlots")
)
),
##### dashboardBody #####
dashboardBody(
tabItems(
##### tab #####
tabItem(
tabName = "sPlots",
tabsetPanel(
tabPanel(
"Sankey plot",
fluidRow(
box(title = "title",
solidHeader = TRUE, collapsible = TRUE, status = "primary",
sankeyNetworkOutput("sankeyHSM1")
)
)
)
)
)
)
)
)
)
server <- function(input, output, session) {
HSM = matrix(rep(c(10000, 700, 10000-700, 200, 500, 50, 20, 10, 2,40,10,10,10,10),4),ncol = 4)
sankeyHSMNetworkFun = function(x,ndx) {
nodes = data.frame("name" = factor(labels, levels = labels),
"group" = as.character(c(1,2,2,3,3,4,4,4,4)))
links = as.data.frame(matrix(byrow=T,ncol=3,c(
0, 1, NA,
0, 2, NA,
1, 3, NA,
1, 4, NA,
3, 5, NA,
3, 6, NA,
3, 7, NA,
3, 8, NA
)))
links[,3] = HSM[2:(nrow(links)+1),] %>% {rowSums(.[,(ndx-1)*2+c(1,2)])}
names(links) = c("source","target","value")
sankeyNetwork(Links = links, Nodes = nodes, Source = "source", Target = "target", Value = "value", NodeID = "name",NodeGroup = "group",
fontSize=12,sinksRight = FALSE)
}
output$sankeyHSM1 = renderSankeyNetwork({
sankeyHSMNetworkFun(values$HSM,1)
})
}
# Run the application
shinyApp(ui = ui, server = server)
----------------编辑--------------------
感谢@CJYetman 指出 onRender()
作为一个可能的解决方案——但是当有两个并排生成的图时,如下面的 MRE 所示,这失败了(注意除了第二个 sankey 图我还有添加了 javascript 代码以在 window 大小发生变化时重新绘制图形,因为绘图似乎不会自动执行)。
library(shiny)
library(magrittr)
library(shinydashboard)
library(networkD3)
library(htmlwidgets)
labels = as.character(1:9)
ui <- tagList(
tags$head(
tags$script('
var dimension = [0, 0];
$(document).on("shiny:connected", function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange("dimension", dimension);
});
$(window).resize(function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange("dimension", dimension);
});
')
),
dashboardPage(
dashboardHeader(
title = "appName"
),
##### dasboardSidebar #####
dashboardSidebar(
sidebarMenu(
id = "sidebar",
menuItem("plots",
tabName = "sPlots")
)
),
##### dashboardBody #####
dashboardBody(
tabItems(
##### tab #####
tabItem(
tabName = "sPlots",
tabsetPanel(
tabPanel(
"Sankey plot",
fluidRow(
box(title = "title",
solidHeader = TRUE, collapsible = TRUE, status = "primary",
sankeyNetworkOutput("sankeyHSM1")
),
box(title = "plot2",
solidHeader = TRUE, collapsible = TRUE, status = "primary",
sankeyNetworkOutput("sankeyHSM2"))
)
)
)
)
)
)
)
)
server <- function(input, output, session) {
HSM = matrix(rep(c(10000, 700, 10000-700, 200, 500, 50, 20, 10, 2,40,10,10,10,10),4),ncol = 4)
sankeyHSMNetworkFun = function(x,ndx) {
nodes = data.frame("name" = factor(labels, levels = labels),
"group" = as.character(c(1,2,2,3,3,4,4,4,4)))
links = as.data.frame(matrix(byrow=T,ncol=3,c(
0, 1, NA,
0, 2, NA,
1, 3, NA,
1, 4, NA,
3, 5, NA,
3, 6, NA,
3, 7, NA,
3, 8, NA
)))
links[,3] = HSM[2:(nrow(links)+1),] %>% {rowSums(.[,(ndx-1)*2+c(1,2)])}
names(links) = c("source","target","value")
sankeyNetwork(Links = links, Nodes = nodes, Source = "source", Target = "target", Value = "value", NodeID = "name",NodeGroup = "group",
fontSize=12,sinksRight = FALSE)
}
output$sankeyHSM1 = renderSankeyNetwork({
req(input$dimension)
sankeyHSMNetworkFun(values$HSM,1) %>%
onRender('document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
})
output$sankeyHSM2 = renderSankeyNetwork({
req(input$dimension)
sankeyHSMNetworkFun(values$HSM,2) %>%
onRender('document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
})
}
# Run the application
shinyApp(ui = ui, server = server)
---------------- 编辑 2 ------------------
上面的第二个问题已解决——根据@CJYetman 在下面的评论使用 document.getElementsByTagName("svg")[1].setAttribute("viewBox","")
引用页面上的第二个 svg 项目,或者通过使用 [=15] 进入对象本身选择它们的第一个 svg 元素=].
这似乎是 Firefox 对 viewbox
svg 属性 的反应不同于其他浏览器的结果。可能值得在此处将其作为问题提交 https://github.com/christophergandrud/networkD3/issues
同时,您可以通过使用 JavaScript 和 htmlwidgets::onRender()
重置 viewbox
属性来解决此问题。这是一个使用示例的最小化版本的示例。 (重置 viewbox
属性可能会产生其他后果)
library(htmlwidgets)
library(networkD3)
library(magrittr)
nodes = data.frame("name" = factor(as.character(1:9)),
"group" = as.character(c(1,2,2,3,3,4,4,4,4)))
links = as.data.frame(matrix(byrow = T, ncol = 3, c(
0, 1, 1400,
0, 2, 18600,
1, 3, 400,
1, 4, 1000,
3, 5, 100,
3, 6, 40,
3, 7, 20,
3, 8, 4
)))
names(links) = c("source","target","value")
sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
NodeGroup = "group", fontSize = 12, sinksRight = FALSE)
htmlwidgets::onRender(sn, 'document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
更新 (2019.10.26)
这可能是一个更安全的移除 viewBox 的实现...
htmlwidgets::onRender(sn, 'function(el) { el.getElementsByTagName("svg")[0].removeAttribute("viewBox") }')
更新 2020.04.02
我目前首选的方法是使用 htmlwidgets::onRender
专门针对传递的 htmlwidget 包含的 SVG,就像这样...
onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
然后可以根据需要专门针对您页面上的尽可能多的 htmlwidgets
执行此操作,例如...
onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
onRender(sn2, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')