3

I am developing this Shiny app and regularly updating it online. Naturally , I work on it locally and upload it every once in a while to check that everything is running smoothly. But I've hit this issue and I cannot seem to get past it.

I am using a custom (Google) font called Source Code Pro on the app, so that the entire app uses this font, graphs included. (For the sake of simplicity I deliberately haven't changed the font of the download button in the minimum reproducible example.) The font is sourced using the showtext package and by running font_add_google("Source Code Pro").

The graphs are produced with ggplot2, then I use ggplotly(...) to produce a plotly graph and finally plotlyOutput and renderPlotly do the rest. The graph itself is produced via a user-defined function called returnChart which returns a ggplot using as inputs the data (sample_data) and some colors (color_ids), and an additional parameter which indicates whether the output will be downloaded or not (download = F is default). This adds a legend to the graph (a legend is not needed in the graph shown on the app due to the plotly tooltip, but this naturally does not work when downloading the graph as a PNG).

When running the app locally and clicking the download button, the downloaded graph's font is Source Code Pro, but this is not the case when the app is run on the shinyapps.io servers. (Originally, it would also fail locally but using the Cairo package fixed that). I have looked into this solution but it does not seem to fix the issue. In any case, I don't think the issue lies with Ubuntu since the custom fonts do work for the plotly plots shown on the app.

Any ideas regarding this are greatly appreciated.

The online app can be found here.

The code runs in the same file in the exact same order as below, but I've split it for ease of reading.

Loading packages, initializing data:

library(ggplot2)
library(tidyverse)
library(showtext)
library(Cairo)
library(shiny)
library(plotly)
library(viridis)
library(PerformanceAnalytics)
options(shiny.usecairo=T)
font_add_google("Source Code Pro")

sample_return1 = c(0.0866, 0.2254, 0.0079, -0.0006, 0.0216,
                  -0.0210, -0.0992, 0.0219, 0.0430, -0.0388,
                  0.2031, 0.0254,-0.0293, 0.0227, 0.0809,
                  0.0129, 0.0024, 0.0361, 0.0047, 0.0292,
                  0.0228,-0.0067, 0.0056, 0.0116,-0.0087,
                  0.0662, 0.1083, 0.0269, 0.0479,-0.0294,
                  -0.0329, 0.0104,-0.1716, 0.1194, 0.0152,
                  0.0389,-0.0026,-0.0381, 0.0568,-0.0873,
                  0.0797, 0.0141, 0.0112, 0.0145,-0.0278,
                  0.0395,-0.0164, 0.1176,-0.0232, 0.0236,
                  0.0306, 0.0210, 0.0333,-0.1140,-0.0780,
                  -0.0490, 0.0270, 0.0200, 0.1140, 0.1110)

sample_return2 = c(0.0336, 0.0891,-0.0096, 0.0211, 0.0483,
                   -0.0869, 0.0575, 0.1442,-0.0911,-0.0413,
                   -0.1383, 0.1542, 0.1088,-0.0886, 0.1515,
                   -0.1050, 0.0244, 0.2322, 0.0269,-0.0011,
                   0.0065, 0.1001, 0.0962,-0.0750, 0.0594, 
                   0.0416, 0.0344,-0.0705,-0.0063,-0.1437,
                   -0.0054, 0.0131,-0.0147, 0.0331, 0.0303,
                   -0.0237,-0.0301, 0.0095,-0.0048, 0.0012, 
                   0.0141, 0.0285, 0.0106,-0.0319, 0.0722, 
                   0.0161,-0.0082,-0.0043, 0.0068,-0.0189,
                   -0.0065,-0.0400, 0.0136, 0.0125,-0.0076,
                   -0.0380, 0.0189, 0.0309,-0.0065, 0.0223,
                   0.0084,-0.0049,-0.0337, 0.0137, 0.0115,
                   -0.0093,-0.0025, 0.0025, 0.0042)




sample_dates1 = as.Date(c("2015-09-30", "2015-10-31", "2015-11-30", 
                         "2015-12-31", "2016-01-31", "2016-02-29", 
                         "2016-03-31", "2016-04-30", "2016-05-31", 
                         "2016-06-30", "2016-07-31", "2016-08-31", 
                         "2016-09-30", "2016-10-31", "2016-11-30", 
                         "2016-12-31", "2017-01-31", "2017-02-28", 
                         "2017-03-31", "2017-04-30", "2017-05-31",
                         "2017-06-30", "2017-07-31", "2017-08-31", 
                         "2017-09-30", "2017-10-31", "2017-11-30", 
                         "2017-12-31", "2018-01-31", "2018-02-28", 
                         "2018-03-31", "2018-04-30", "2018-05-31", 
                         "2018-06-30", "2018-07-31", "2018-08-31", 
                         "2018-09-30", "2018-10-31", "2018-11-30", 
                         "2018-12-31", "2019-01-31", "2019-02-28",
                         "2019-03-31", "2019-04-30", "2019-05-31", 
                         "2019-06-30", "2019-07-31", "2019-08-31", 
                         "2019-09-30", "2019-10-31", "2019-11-30", 
                         "2019-12-31", "2020-01-31", "2020-02-29", 
                         "2020-03-31", "2020-04-30", "2020-05-31", 
                         "2020-06-30", "2020-07-31", "2020-08-31"))

sample_dates2 = as.Date(c( "2015-01-31", "2015-02-28", "2015-03-31", 
                           "2015-04-30", "2015-05-31", "2015-06-30", 
                           "2015-07-31", "2015-08-31", "2015-09-30", 
                           "2015-10-31", "2015-11-30", "2015-12-31", 
                           "2016-01-31", "2016-02-29", "2016-03-31", 
                           "2016-04-30", "2016-05-31", "2016-06-30", 
                           "2016-07-31", "2016-08-31", "2016-09-30",
                           "2016-10-31", "2016-11-30", "2016-12-31", 
                           "2017-01-31", "2017-02-28", "2017-03-31", 
                           "2017-04-30", "2017-05-31", "2017-06-30", 
                           "2017-07-31", "2017-08-31", "2017-09-30", 
                           "2017-10-31", "2017-11-30", "2017-12-31", 
                           "2018-01-31", "2018-02-28", "2018-03-31", 
                           "2018-04-30", "2018-05-31", "2018-06-30",
                           "2018-07-31", "2018-08-31", "2018-09-30", 
                           "2018-10-31", "2018-11-30", "2018-12-31", 
                           "2019-01-31", "2019-02-28", "2019-03-31", 
                           "2019-04-30", "2019-05-31", "2019-06-30", 
                           "2019-07-31", "2019-08-31", "2019-09-30", 
                           "2019-10-31", "2019-11-30", "2019-12-31", 
                           "2020-01-31", "2020-02-29", "2020-03-31",
                           "2020-04-30", "2020-05-31", "2020-06-30", 
                           "2020-07-31", "2020-08-31", "2020-09-30"))

sample_name = c(rep("Quantamental", length(sample_return1)), 
                    rep("St. Gallen", length(sample_return2)))

sample_data = data.frame(Date = c(sample_dates1, sample_dates2),
                         Return = c(sample_return1, sample_return2),
                         Program = sample_name)

color_ids = viridis(2)

The returnChart function:

returnChart <- function(sample_data, color_ids, download = F){

p <- ggplot(data = sample_data,
            aes(x = Date, y = Return, color = Program, group = Program,
                text = paste0("Program: ", Program, "\n",
                              "Return: ", round(100*Return, 1), "%\n",
                              "Date: ", as.character(as.yearmon(Date)), "\n"))) +
  geom_line() +
  theme_bw() +
  scale_y_continuous(labels=scales::percent) +
  scale_color_manual(name = "Program", values = color_ids) +
  theme(axis.title.x = element_text(family = "Source Code Pro"),
        axis.title.y = element_text(family = "Source Code Pro"),
        axis.text.x = element_text(family = "Source Code Pro"),
        axis.text.y = element_text(family = "Source Code Pro"))

if (download == T){
  p <- p + 
    theme(legend.position = "bottom",
          legend.title = element_text(size = 8, family = "Source Code Pro"),
          legend.text = element_text(size = 6, family = "Source Code Pro")) +
    guides(color=guide_legend(nrow=ceiling(length(unique(sample_data$Program))/2),
                              byrow=TRUE, override.aes = list(size = 0.5)))
}

return(p)

}

The Shiny app:

ui <- shinyUI(
  mainPanel(
    plotlyOutput("returnPlot"),
    downloadButton("downloadReturn", "Download")
  )
)

server <- shinyServer(function(input, output, session){
  
  output$returnPlot <- renderPlotly({
      
      p <- returnChart(sample_data, color_ids)
      
      p <- p +
        theme(legend.position = "none") +
        theme(legend.title = element_blank())
      
      ggplotly(p, tooltip = c("text")) %>%
        config(modeBarButtonsToRemove = list("toImage"))
      
      
  })
  
  output$downloadReturn <- downloadHandler(
    filename = function(){
      "Return_Graph.png"
    },
    content = function(file) {
      
      png(file, width = 16, height = 9, units = 'cm', res = 300, 
          type = "cairo")
      
      print(returnChart(sample_data, color_ids, download = T))
      
      dev.off()
    },
    contentType = 'image/png'
  )
  
})


shinyApp(server = server, ui = ui)
  • 1
    Is this really a minimal(!) reproducible example? I doubt that e.g. "data" is important to your question. – Christoph Oct 13 '20 at 12:13
  • Did you try `{showtext}` package which handle fonts issue quite well? – Emrick Liu Oct 14 '20 at 09:27
  • I figured it out - for some reason, magick was disabling the cairo package in the online shinyapps.io server but not when I was running it locally. This was to add a logo from a PNG to the graphs. I found another way to do it, but it's still annoying not to be able to use magick. – Alex Lostado Oct 14 '20 at 15:40
  • 1
    @AlexLostado Great that you've found a solution! Please share your solution as an answer (and accept it). This will help others with the same problem later – starja Oct 15 '20 at 19:35

0 Answers0