Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sankey very small with firefox #97

Open
smartinsightsfromdata opened this issue Dec 13, 2015 · 29 comments
Open

sankey very small with firefox #97

smartinsightsfromdata opened this issue Dec 13, 2015 · 29 comments

Comments

@smartinsightsfromdata
Copy link

I have a simple shiny app with a sankey chart. It works on all browsers, but in Firefox is incredibly small to the point of been unusable. Could it be a recent regression?

Mozilla Firefox ESR 38.4.0 on Centos 7. I've given below a snippet of the code and my sessionInfo() details.
I've tried to use height and width (see below) as a way to avoid the issue with no luck.

output$sankey <- renderSankeyNetwork({  

networkD3::sankeyNetwork(Links = clink, Nodes = cnodes, Source = "source",
                          Target = "target", Value = "value", NodeID = "id", 
                          colourScale = JS("d3.scale.category20()") , 
                         fontSize = 12, nodeWidth = 30, height = 700, width = 500)
})
sessionInfo()
R version 3.2.2 (2015-08-14)
Platform: x86_64-redhat-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

locale:
 [1] LC_CTYPE=en_GB.UTF-8      
 [2] LC_NUMERIC=C              
 [3] LC_TIME=en_GB.UTF-8       
 [4] LC_COLLATE=en_GB.UTF-8    
 [5] LC_MONETARY=en_GB.UTF-8   
 [6] LC_MESSAGES=en_GB.UTF-8   
 [7] LC_PAPER=en_GB.UTF-8      
 [8] LC_NAME=C                 
 [9] LC_ADDRESS=C              
[10] LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_GB.UTF-8
[12] LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils    
[5] datasets  methods   base     

other attached packages:
 [1] dplyr_0.4.3        networkD3_0.2.7   
 [3] jsonlite_0.9.19    RColorBrewer_1.1-2
 [5] classInt_0.1-23    leaflet_1.0.0     
 [7] data.table_1.9.6   maptools_0.8-37   
 [9] rgeos_0.3-15       rgdal_1.1-1       
[11] sp_1.2-1           shiny_0.12.2      

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.2     magrittr_1.5   
 [3] xtable_1.8-0    lattice_0.20-33
 [5] R6_2.1.1        tools_3.2.2    
 [7] parallel_3.2.2  grid_3.2.2     
 [9] DBI_0.3.1       e1071_1.6-7    
[11] htmltools_0.2.6 class_7.3-13   
[13] yaml_2.1.13     assertthat_0.1 
[15] digest_0.6.8    htmlwidgets_0.5
[17] mime_0.4        httpuv_1.3.3   
[19] foreign_0.8-65  chron_2.3-47  
@askene
Copy link

askene commented Feb 19, 2016

I am seeing the same issue in Chrome, Firefox, and Safari when running from a shiny-server instance. This does not show up when the app is started in RStudio.

It looks like the issue is related to how the viewbox is calculated here:
https://github.com/christophergandrud/networkD3/blob/master/inst/htmlwidgets/sankeyNetwork.js#L186

The app I'm using modifies the data used to generate the diagram. Sometimes this ends up fine, other times it completely breaks the viewbox calculations and ends up with a tiny diagram.

Removing the viewbox attribute completely solved the issue for me, but lost the dynamic resizing when changing the browser window size. I'm going to try to track down the problem with the calculations, but may just stick with my fix of not using the viewbox at all.

@timelyportfolio
Copy link
Collaborator

I'm wondering if this might be a race condition and possibly related to this StackOverflow. Unfortunately, I can't reproduce these on my side, so I'm not sure how to debug.

@timelyportfolio
Copy link
Collaborator

Can you update to the github version of Shiny and htmlwidgets to make sure these don't cure the problem? I don't remember any changes that would have addressed this problem, but at least we will be able to eliminate this as a potential source of the problem.

@timelyportfolio
Copy link
Collaborator

Thinking through this, are there cycles in your network? We added support for cycles in Sankey that could potentially have introduced a regression.

@timelyportfolio
Copy link
Collaborator

For reference, this is the code I am using to test.

library(networkD3)
library(shiny)

# simple network with cycles
net_cycles <- list(
  links = data.frame(
    source = c(0,0,0,1,1,5),
    target = c(1,2,3,4,5,0),
    value = 10
  ),
  nodes = data.frame(
    name = letters[1:6]
  )
)

URL <- paste0("https://cdn.rawgit.com/christophergandrud/networkD3/",
              "master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)

ui <- fluidPage(fluidRow(
  column(6,sankeyNetworkOutput("sankey",height=300)),
  column(6,sankeyNetworkOutput("sankey2",height=300))
))

# notice how few arguments we need now
# some output but not the nice output I expect
server <- function(input,output,session){
  output$sankey <- renderSankeyNetwork({
    invalidateLater(1000)
    sankeyNetwork(
      net_cycles$links,
      net_cycles$nodes,
      Value = "value"
    )
  })

  output$sankey2  <- renderSankeyNetwork({
    invalidateLater(1000)
    sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
                  Target = "target", Value = "value", NodeID = "name",
                  units = "TWh", fontSize = 12, nodeWidth = 30)
  })
}

shinyApp(ui,server)

@askene
Copy link

askene commented Feb 29, 2016

I upgraded to the latest github versions of htmltools, shiny, and networkD3, but I am still seeing some strange behavior. To clarify, this only shows up when I run the code from the a shiny server instance. Not when I run it out of rstudio. I am running this on the latest shiny-server v 1.4.2 built from github's master branch.

The test code you posted seems to jump around on every refresh. The cycles render fine, but move up and down a lot. The energy diagram grows and shrinks.
I added console.log(s.attr("viewBox")) to see the viewBox values on each refresh.

This is what I see for the energy diagram.

-11.399993896484375,-18.649993896484375,625.7000122070312,325.2166748046875 sankeyNetwork.js:221:1
12.600006103515625,-1.5666656494140625,580.2999877929688,303.3500061035156 sankeyNetwork.js:221:1
-8.166671752929688,-17.116668701171875,619.25,322.1000061035156 sankeyNetwork.js:221:1
9.98333740234375,-2.8166656494140625,585.5166625976562,305.8666687011719 sankeyNetwork.js:221:1
-5.75,-15.916671752929688,614.4666748046875,319.8000030517578 sankeyNetwork.js:221:1
8,-3.8166656494140625,589.4500122070312,307.76666259765625 sankeyNetwork.js:221:1
-3.9666595458984375,-14.966659545898438,610.9500122070312,318.0833282470703 sankeyNetwork.js:221:1
6.48333740234375,-4.616668701171875,592.4166259765625,309.183349609375 sankeyNetwork.js:221:1
-2.616668701171875,-14.216659545898438,608.316650390625,316.8333282470703

Shrinking the browser window seems to exacerbates the issue.

-82.96665954589844,5.6666717529296875,563.316650390625,289.0666809082031 sankeyNetwork.js:221:1
92.71665954589844,-24.48333740234375,662.9166870117188,335.8833312988281 sankeyNetwork.js:221:1
-75.96665954589844,35.44999694824219,320.2166748046875,229.75 sankeyNetwork.js:221:1
101.85000610351562,-64.53334045410156,590,412.5 sankeyNetwork.js:221:1
-81.86666870117188,27.899993896484375,346.33331298828125,247.2666778564453 sankeyNetwork.js:221:1
100.14999389648438,-52.21665954589844,551.0499877929688,386.40000915527344 sankeyNetwork.js:221:1
-84.5,21.583328247070312,367.0333251953125,261.1166687011719 sankeyNetwork.js:221:1
96.61666870117188,-43.25,523.933349609375,367.2333526611328 sankeyNetwork.js:221:1
-85.41667175292969,16.433334350585938,384.1000061035156,273.5500030517578 sankeyNetwork.js:221:1
92.98333740234375,-36.55000305175781,501.933349609375,352.5166778564453 sankeyNetwork.js:221:1
-84.89999389648438,12.25,398.4666748046875,283.16668701171875

The initial code that I've got usually ends up with a large negative x offset, which I think is where the shrinking comes from.
I'm not sure where in the viewBox calculation things are breaking, but that seems to be the most logical place to fix things.

@smartinsightsfromdata
Copy link
Author

I tried @timelyportfolio code on my apple mac.

If I display in the browser, and the browser is Firefox, I have the problem (but while the two viz are smaller, they do not seems as small as a single viz would looks like).

I do not seem to have the problem with Chrome though.

@ChristelSwift
Copy link

same problem when rendering a Sankey from R Markdown to html: tiny on firefox, fine on chrome and safari... is there a workaround to get to a normal size in firefox...?

@cjyetman
Copy link
Collaborator

cjyetman commented Aug 1, 2018

Pretty sure this is caused by the viewbox SVG property. I gave the following solution to a user on Stack Overflow and it satisfied their specific use case. Can you check if some variant of this works in your case as well?

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", "")')

@ChristelSwift
Copy link

ChristelSwift commented Aug 2, 2018

thank you so much! it works great for 1 chart, but i'm having trouble with multiple charts, despite adding the onRender and updating the number in square brackets each time... any idea how to fix this? Here's my code using your data (only the 1st chart renders):

sn1 <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source", 
                    Target = "target", Value = "value", NodeID = "name", 
                    NodeGroup = "group", fontSize = 12)

htmlwidgets::onRender(sn1, 'document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')

same chart with sinksRight = FALSE:

sn2 <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source", 
                    Target = "target", Value = "value", NodeID = "name", 
                    NodeGroup = "group", fontSize = 12, sinksRight = FALSE)

htmlwidgets::onRender(sn2, 'document.getElementsByTagName("svg")[1].setAttribute("viewBox", "")')

@cjyetman
Copy link
Collaborator

cjyetman commented Aug 2, 2018

You'll have to provide a full, reproducible example, because that works for me.

@cjyetman
Copy link
Collaborator

cjyetman commented Aug 2, 2018

and technically, these issues are not meant to be used as a support forum, so it may be better to create a question on Stack Overflow

@ChristelSwift
Copy link

ChristelSwift commented Aug 2, 2018

sorry - i'll add it to the existing thread on stackoverflow.

@ghost
Copy link

ghost commented Mar 4, 2019

I basically have the same thing happening as well. I have a Sankey Network I'm using with the R blogdown package. And my Sankey Network also renders fine in Chrome and IE11, but is very small in Firefox. My StackOverflow question can be seen here. I tried @cjyetman previous solution but it doesn't appear to work in my case.

@cjyetman
Copy link
Collaborator

cjyetman commented Mar 4, 2019

@jhuntergit can you put a reprex here to match your comment please? If it’s not the same issue as here, which it sounds like it might not be, then we should open a new issue to figure it out.

@ghost
Copy link

ghost commented Mar 5, 2019

I think it's the same issue. The only difference is I'm running this code as an R blogdown site. Here is the code that generates a small Sankey Network, but only in Firefox. In Chrome and IE this same Sankey Network is normal sized.


---
    title: "Data Analysis"
    date: "2019-01-01T18:00:00-09:00"
    ---
    
    ```{r setup, include=FALSE}
    knitr::opts_chunk$set(echo = TRUE)
    library(tidyverse)
    library(blogdown)
    library(networkD3)
    ```
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    
    ```{r sankey, echo=FALSE, error=FALSE, message=FALSE, warning=FALSE}
    source <- c("A", "A", "B", "C", "D", "D", "E", "E")
    target <- c("D", "E", "E", "D", "H", "I", "I", "H")
    values <- c(1, 22, 5, 5, 5, 10, 10, 10)
    nodes <- data.frame(name = unique(c(source, target)))
    links <- data.frame(source = match(source, nodes$name) - 1,
                        target = match(target, nodes$name) - 1,
                        value = values)
    sankeyNetwork(Links = links, Nodes = nodes, Source = "source", 
                  Target = "target", Value = "value", NodeID = "name", 
                  units = "unitX", fontSize = 12, nodeWidth = 20)
    ```

@cjyetman
Copy link
Collaborator

cjyetman commented Mar 5, 2019

this works for me (macOS 10.14.3, Firefox 65.0.1)

---
title: "Data Analysis"
date: "2019-01-01T18:00:00-09:00"
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(blogdown)
library(networkD3)
```

Lorem ipsum dolor sit amet.

```{r sankey, echo=FALSE, error=FALSE, message=FALSE, warning=FALSE}
source <- c("A", "A", "B", "C", "D", "D", "E", "E")
target <- c("D", "E", "E", "D", "H", "I", "I", "H")
values <- c(1, 22, 5, 5, 5, 10, 10, 10)
nodes <- data.frame(name = unique(c(source, target)))
links <- data.frame(source = match(source, nodes$name) - 1,
                    target = match(target, nodes$name) - 1,
                    value = values)

sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source", 
                    Target = "target", Value = "value", NodeID = "name", 
                    units = "unitX", fontSize = 12, nodeWidth = 20)

htmlwidgets::onRender(sn, 'document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
```

@cjyetman
Copy link
Collaborator

cjyetman commented Mar 5, 2019

@jhuntergit can you attach the generated HTML file that you get from running my example code above (the version that has the fix that works on my computer). I'll test if your generated HTML code works on my machine as expected in Firefox and/or if it's the same as the HTML generated on my machine. If our HTML files are the same, then yeah, unfortunately it's a difference between OS and browser environments, which I can't easily investigate. Otherwise, there must be some reason you're getting a different HTML output than I am using the same code.

@ghost
Copy link

ghost commented Mar 6, 2019

Will do. I just need to put the request on pause for the next week or so. Currently the site only exists when I serve it through blogdown and R Studio. The static HTML files don't display properly unless served via blogdown within R Studio. When I deploy the site soon, I'll also grab the static HTML and attach here and @ mention you so you'll be aware. Thanks for your patience.

@cjyetman
Copy link
Collaborator

cjyetman commented Mar 6, 2019

@jhuntergit thanks for your willingness, but please do not attach a page from your website here. That doesn’t have any relevance here. Only attach the HTML output from running precisely the above Rmd code, no more, no less. Anything more/other than that will only complicate things and make me waste time investigating it.

@ghost
Copy link

ghost commented Mar 10, 2019

@cjyetman I can do that. Do you want the output from my R console? That is simply the block shown below. As I'm building my website I'm serving it locally using the R package blowdown. Or the HTML output I'd get from right clicking and View Page Source within Firefox?


> blogdown::serve_site()
Building sites … 
                   | EN  
+------------------+----+
  Pages            | 21  
  Paginator pages  |  0  
  Non-page files   |  0  
  Static files     | 36  
  Processed images |  0  
  Aliases          |  0  
  Sitemaps         |  1  
  Cleaned          |  0  

Total in 521 ms
To stop the server, run servr::daemon_stop(1) or restart your R session
Serving the directory /home/j/blogdown-website at http://127.0.0.1:4321

@cjyetman
Copy link
Collaborator

Definitely don’t want the R console output. Just one HTML file.

Still looks like you’re trying to show me your webpage. I don’t want that. I want the output from my example.

@ghost
Copy link

ghost commented Mar 16, 2019

@cjyetman I determined what my issue is. I can run your code block above and it works exactly as expected, BUT, only in isolation. If you look at the same R chunk below, except I added a "radial network" chunk, which neutralizes your htmlwidgets::onRender(sn, 'document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")') solution.

Try and run this code chunk and you'll discover Firefox makes the Sankey Network small again. Why does the "radial network" chunk neutralize your solution? And how do I work around this? Yes, I need to keep the radial network in this R Markdown document. Thanks

*and sorry I can't really get this complete *.Rmd file to format properly on this Github forum, if you copy paste the following into R Studio, then select all, then Shift+Tab to remove the first two spaces it should work within R Studio

---
title: "Data Analysis"
date: "2019-01-01T18:00:00-09:00"
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(blogdown)
library(networkD3)
```

```{r radial network, echo=FALSE, error=FALSE, message=FALSE, warning=FALSE}
nd3 <- list(name = "Start", children = list(list(name = "A",
                                          children = list(list(name = 		"1"),
                                                          list(name = 		"2"),
                                                          list(name = 		"3")
                                                          		)),

                                         		list(name = "B")))
diagonalNetwork(List = nd3, fontSize = 10, opacity = 0.9)
```

Lorem ipsum dolor sit amet.

```{r sankey, echo=FALSE, error=FALSE, message=FALSE, warning=FALSE}
source <- c("A", "A", "B", "C", "D", "D", "E", "E")
target <- c("D", "E", "E", "D", "H", "I", "I", "H")
values <- c(1, 22, 5, 5, 5, 10, 10, 10)
nodes <- data.frame(name = unique(c(source, target)))
links <- data.frame(source = match(source, nodes$name) - 1,
            		target = match(target, nodes$name) - 1,
            		value = values)

sn <- sankeyNetwork(Links = links, Nodes = nodes, Source = "source", 
            		Target = "target", Value = "value", NodeID = "name", 
            		units = "unitX", fontSize = 12, nodeWidth = 20)

htmlwidgets::onRender(sn, 		'document.getElementsByTagName("svg")[0].setAttribute("viewBox", "")')
```

@cjyetman
Copy link
Collaborator

Great, thanks. I’m on vacation for the next 10 days or so, but this reduced/minimized example is probably exactly what I need to figure it out.

@cjyetman
Copy link
Collaborator

Without being able to try it out myself, I can make a guess already that there should be a [1] instead of a [0] in the JavaScript you’re passing with htmlwidgets::onRender since the diagonal network is probably runs first and would be the first SVG element.

Also please do not refer to the plot produced by diagonalNetwork as a radial network to avoid confusion.

@ghost
Copy link

ghost commented Mar 16, 2019

@cjyetman yes - right again! I stepped up [0] sequentially in increments of 1 and the first try everything worked. I'll continue doing that going forward when I am using multiple networkD3 elements in one *.Rmd document. Thank you. Enjoy the vacation. Well deserved.

@gdmcdonald
Copy link

I encountered this same problem today, here's how I fixed it:

Put this code in your Rmd somewhere to loop through and set all the svg's viewBox = null.

htmlwidgets::onStaticRenderComplete('$.each( document.getElementsByTagName("svg"), function( index, value ){value.setAttribute("viewBox", null);});')

@cjyetman
Copy link
Collaborator

cjyetman commented Apr 2, 2020

Just be aware that...

htmlwidgets::onStaticRenderComplete('$.each( document.getElementsByTagName("svg"), function( index, value ){value.setAttribute("viewBox", null);});')

requires jQuery and removes the viewBox from every SVG on the page, no matter what they are or where they came from.

My currently preferred method to do this is to use htmlwidgets::onRender to target specifically the SVG contained by the passed htmlwidget, like this...

onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')

That can be done on each htmlwidget necessary, specifically. For example, using an example from above...

library(networkD3)
library(shiny)
library(htmlwidgets)

# simple network with cycles
net_cycles <- list(
  links = data.frame(
    source = c(0,0,0,1,1,5),
    target = c(1,2,3,4,5,0),
    value = 10
  ),
  nodes = data.frame(
    name = letters[1:6]
  )
)

URL <- paste0("https://cdn.rawgit.com/christophergandrud/networkD3/",
              "master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)

ui <- fluidPage(fluidRow(
  column(6,sankeyNetworkOutput("sankey",height=300)),
  column(6,sankeyNetworkOutput("sankey2",height=300))
))

# notice how few arguments we need now
# some output but not the nice output I expect
server <- function(input,output,session){
  output$sankey <- renderSankeyNetwork({
    invalidateLater(1000)
    sn <- sankeyNetwork(net_cycles$links, net_cycles$nodes, Value = "value")
    onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
  })
  
  output$sankey2  <- renderSankeyNetwork({
    invalidateLater(1000)
    sn2 <- sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
                  Target = "target", Value = "value", NodeID = "name",
                  units = "TWh", fontSize = 12, nodeWidth = 30)
    onRender(sn2, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')
  })
}

shinyApp(ui,server)

@chapb
Copy link

chapb commented Nov 22, 2021

I wanted to add my thanks to @cjyetman and @gdmcdonald. The viewBox property is definitely the issue at hand, and this was the only solution I found to fix it at render.

For completeness, I'll add that if you're saving a stand-alone network to a .HTML file, you can do something like this to take advantage of the fix:

output <- onRender(sn, 'function(el) { el.querySelector("svg").removeAttribute("viewBox") }')

saveNetwork(output, path)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants