rstudio / webshot2

Take screenshots of web pages from R

Home Page:https://rstudio.github.io/webshot2/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Image truncated and white borders using gtsave() function

Fedess1986 opened this issue · comments

I'm trying to export a gt table created using the gtsave() function, as PNG file.

The generated PNG has some white border at the left, and sometime at botton and top too. Also, the right side of the image is cropped/truncated.
The gtsave() generates a html temp file to get the shot, which I can locate and check the table looks correct (I open that html file with chrome).

I tryed changing and playing vwidth, vheight, zoom, expand, and selector arguments, with no luck.

I can upload some screenshots for references, if needed

Hi @Fedess1986 and thanks for the report. Screenshots might be helpful, but it'd be even more helpful to include a reproducible example (or reprex).

For some reason I cannot make reprex() work, anyway I did my best.


library(dplyr)
library(gt)
library(gtExtras)


# I just create a table with similar data I work with

table <- data.frame(
           Provider = c("provider1_a_long_name_for_testing", "provider2", "provider3", "provider4", "provider5", "provider6", "provider7", "provider8", "provider9", "provider10"),
           Expenses = c(10000000, 8000000, 7000000, 4000000, 3500000, 3000000, 2000000, 500000,450000,200000),
           Value1 = c(100,105,110,120,130,150,160,170,180,190)*1001,
           Value2 = c(200,205,209,220,230,250,260,270,280,290)*1002,
           Value3_longer = c(300,305,309,320,330,350,360,370,380,390)*1003
           )

Qty_evolution  <-  list(
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5))
           )

table$Qty_evolution <- Qty_evolution



# Here I create the gttable I would like to export as PNG image

gt_table <-  table %>% select(Provider, Expenses, Qty_evolution, Value1, Value2, Value3_longer) %>%   gt() %>% 
  tab_header(
    title = "The title of this table",
    subtitle = "Then, the subtitle")   %>% 
  tab_source_note(source_note = "ALso I'm using a source note."  ) %>% 
  tab_style(style = cell_text(align = "center"),locations = cells_source_notes()) %>%  
   tab_spanner(
    label = "Actual value - and giving this a long name too",
    columns = c(Value1, Value2, Value3_longer)
  ) %>% 
  fmt_currency(columns = Value1:Value3_longer, decimals = 0, sep_mark = ".",
  dec_mark = ",") %>% 
  gt_plt_bar(column = Expenses, keep_column = FALSE, color = "#5064FF",width = 50) %>% gt_plt_sparkline(column = Qty_evolution, fig_dim = c(14, 60), palette = c("#7EC9FF", "gray96", "green", "red", "lightgrey"),) %>% 
  tab_options(table.background.color = ("gray19"), table.font.color = "gray90", heading.title.font.size = 24,  heading.title.font.weight = "bold" ,heading.subtitle.font.size = 20,
table.font.size = 14,
column_labels.font.size = 16,
  row_group.border.top.color = "gray35",
  table.border.top.color = "gray35",
  heading.border.bottom.color = "gray35",
table_body.hlines.color = "gray35",
table_body.vlines.color = "gray35", 
table_body.border.top.color = "gray35",
table_body.border.bottom.color = "gray35",
heading.border.lr.color = "gray35",
 column_labels.border.bottom.color = "gray35",
column_labels.vlines.color = "gray35", 
column_labels.border.lr.color = "gray35"
  )
 

# This is the functions that internally uses webshot
gtsave(gt_table, filename = "test.PNG", zoom = 1)

 

Also, locating the html file, what I do is:
Edit: I share this part because I believe it helps finding out where the problem is or is not, I think it is not related with th gt package, as the result using directly webshot and coming from a html file is the same.



webshot2::webshot(url = "reproducible.html", file = "test2.png",
                  zoom = 1)

And result is exactly the same

Thanks for the example code @Fedess1986. I'm not surprised that reprex() gave you some trouble, this kind of issue tends to be tricky for reprex().

I linked to the package for its helpful advice about creating a reproducible, minimal example. Are all of the packages and code in your example required to reproduce the problem? If not, it would also be helpful if you could reduce the example code to the smallest subset of packages and lines and are needed to reproduce the issue. (Often you'll find important clues in this process.)

Thanks for the advice. I managed to rewrite the code without the "dplyr" package. Also I reduced the code by quitting many visual options that are not needed, and the issue still happens.
The "gt" package is required to create the table which contains graphics inside it, those graphics (like the sparkline) created with "gtExtras" package. The result is what I'm trying to render/get the screenshot, so both packages are needed, as I understand.

Here is the new code. I hope this helps 😀


library(gt)
library(gtExtras)


# I just create a table with similar data I work with

table <- data.frame(
           Provider = c("provider1_a_long_name_for_testing", "provider2", "provider3", "provider4", "provider5", "provider6", "provider7", "provider8", "provider9", "provider10"),
           Expenses = c(10000000, 8000000, 7000000, 4000000, 3500000, 3000000, 2000000, 500000,450000,200000))

Qty_evolution  <-   list(
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5)),
           c(rep(c(5,8,10,15,25,20,17,18,22,16), 5))
           )

table$Qty_evolution <- Qty_evolution

table <-  cbind(table,data.frame(
           Value1 = c(100,105,110,120,130,150,160,170,180,190)*1001,
           Value2 = c(200,205,209,220,230,250,260,270,280,290)*1002,
           Value3_longer = c(300,305,309,320,330,350,360,370,380,390)*1003
           ))




# Here I create the gttable I would like to export as PNG image

gt_table <- gt(table) 
gt_table <- tab_header(gt_table, title = "The title of this table")
gt_table <- tab_source_note(gt_table, source_note = "Also I'm using a source note.")
gt_table <- tab_style(gt_table, style = cell_text(align = "center"),locations = cells_source_notes())
gt_table <- tab_spanner(gt_table,  label = "Actual value - and giving this a long name too", columns = c(Value1, Value2, Value3_longer)) 
gt_table <- fmt_currency(gt_table, columns = Value1:Value3_longer, decimals = 0, sep_mark = ".", dec_mark = ",")
gt_table <- gt_plt_bar(gt_table, column = Expenses, keep_column = FALSE, color = "#5064FF",width = 50)
gt_table <- gt_plt_sparkline(gt_table,column = Qty_evolution, fig_dim = c(14, 60), palette = c("#7EC9FF", "gray96", "green", "red", "lightgrey"))
  
   

# This is the functions that internally uses webshot
gtsave(gt_table, filename = "test.PNG")

Thanks @Fedess1986, I can reproduce your issue and I have a quick solution for you.

webshot2::webshot() has two argument to control the width and height of the virtual browser screen: vwidth and vheight. These are set to 992x774 by default, but your table is wider than 992 pixels. If you set vwidth wider, gtsave() will pass that value to webshot() and you'll get the uncropped table image.

gtsave(gt_table, filename = "test.PNG", vwidth = 1200, vheight = 1200)

In general: it's pretty safe to set this to a larger value for saving a table.

I'm going to leave this issue open because webshot2 should probably adapt to changes I made in rstudio/chromote#129 (for my notes see rstudio/shinytest2#367 for additional context).

Thank you for the workaround and for the aditional info, I managed to make it work.

However I want to share this too:
Using the gt() library, I found I can define the pixels width of the table with tab_options( table.width = px() ) . So I set that to 900 pixels. Then, when I did gtsave(gt_table, filename = "test.PNG", vwidth = 900) and a white boder appeared at the right, again getting the table image truncated. I could fix it by increasing vwidth so I set it to 1000 pixels and then it worked fine.

FYI, the exported image has 1800 pixels width (zoom is default 2 so 900px * 2 is giving me those 1800 pixels, If I'm not wrong)

@Fedess1986 Limiting the table width is also a nice approach. Note that if the table width is less than 992px (minus some padding, so approx 980px), then you don't need to set vwidth in gtsave(). And you're right, gtsave() sets an option in webshot() to scale the images size up by a factor of 2, which is why vwdith = 900 gives an image width of 1800px. This results in better resolution in the image.

Thanks for your help and all your feedback. With your suggestions It's now working and covering my need. I'm also glad if this was helpful to you to help improving the library code.