priism-center / shinyquiz

R package for creating quizzes within R Shiny
https://priism-center.github.io/shinyquiz/
Other
3 stars 2 forks source link

Accessing a Local Image in CSS within an R Package #4

Closed TarJae closed 4 months ago

TarJae commented 4 months ago

I am working on incorporating a local image into the CSS for use in the .confetti-piece class, but I'm unsure how to properly reference a locally stored image in the CSS file within an R package. Here's what I have:

.confetti-piece {
    position: absolute;
    width: 10px;
    height: 30px;
    background: #ffd300;
    top: 0;
    opacity: 0;
}

.confetti-piece {
    position: absolute;
    width: 10px;
    height: 30px;
    background: #ffd300;
    background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/R_logo.svg/724px-R_logo.svg.png");
    top: 0;
    opacity: 0;
}

The above CSS works perfectly with the external URL. However, I would like to use a local version of the image that I've stored at inst/www/724px-R_logo.svg.png within the R package. While I found guidance on including images in R packages here on Stack Overflow, I'm not clear on how to reference this local image directly in the CSS file.

How can I correctly link to a locally stored image in the package's CSS file?

joemarlo commented 4 months ago

I believe the url reference is relative to the CSS file. If your css file and the image are in the same directory, it should be url("R_logo.svg"). If it is in another directory, then you can use the standard method to navigate the directory structure: url("../otherDir/R_logo.svg"). Typically you would store both the css file and the image in the /www directory. You might try a few different paths to figure out the one that works.

I'm surprised you can get your external image to work. You can typically override previous css declarations with a new declaration but since shinyquiz injects the css into the <head>, I think that will take precedent over a css file in /www.

If you're modifying the shinyquiz package directly (rather than including the image in your shiny app directory) then all bets are off. You'll probably have to include a /www directory somehow and then place the image in there.

TarJae commented 4 months ago

Thank you very much for your reply. Perhaps I'm on the wrong track. I am attempting to modify shinyquiz by adding a background image to the .confetti-piece class. This approach works for images sourced from the internet but not for those stored locally. I'm fairly certain that I have explored all possible file paths and folders... but I will try further and report. Thank you again!

joemarlo commented 4 months ago

Hmm. I tried replicating your code with the external url but it didn't work for me. If you can provide a reprex, I might be able to figure out a way to use an internal url.

I think ideally the solution would use the shinyquiz package as-is and you would include a new css sheet in the /www directory of your app. That sheet would then override the package's /inst/shinyquiz.css sheet. I'm not 100% sure it will work but it seems like the most maintainable and customizable solution.

TarJae commented 4 months ago

Thank you again. I'll try this out. May I ask another brief question? I could open an issue if it's necessary. I'm trying to access values that are calculated in the package for use in a new app. For example, the $score is calculated in the package, but how can I display it on the screen of the new app, or fetch it for further calculations? I understand this is a theoretical question, but there is a gap in my knowledge here. Thank you very much.

joemarlo commented 4 months ago

There is some documentation here but admittedly not much. shinyquiz::quiz_server() returns back a reactive object that includes the score. You can then do whatever you'd like with that reactive. If you aren't familiar with reactivity, you may want to take a look at this page in Mastering Shiny.

Here's a basic app to show the score in the UI to get you started:

library(shiny)
library(shinyquiz)

# quiz
quiz <- create_quiz(
  create_question(
    'What is the capital of Illinois?',
    add_choice('Chicago'),
    add_choice('Paw Paw'),
    add_choice('Springfield', correct = TRUE)
  ),
  create_question(
    'Which elements are gases at room temperature? Select all that apply.',
    add_choice('Hydrogen', correct = TRUE),
    add_choice('Mercury'),
    add_choice('Nitrogen', correct = TRUE),
    label = 'Select Hydrogen and Nitrogen'
  ),
  create_question(
    'At what temperature does water boil at sea level?',
    add_slider(min = 90, max = 150, default_position = 120, correct = 100),
    label = 'Select 100'
  ),
  options = set_quiz_options(end_on_first_wrong = FALSE)
)

# UI
ui <- fluidPage(
  h3('My Excellent Shiny App'),
  uiOutput(outputId = 'score'),
  quiz_ui(quiz)
)

# Server
server <- function(input, output) {
  quiz_summary <- quiz_server(quiz)
  output$score <- shiny::renderUI({
    # calculate scores
    total_score <- quiz_summary()$score_pretty
    score_so_far <- mean(na.omit(quiz_summary()$which_correct))
    score_so_far <- ifelse(!isTruthy(score_so_far), 0, score_so_far)
    score_so_far <- scales::label_percent()(score_so_far)

    # show score as HTML
    htmltools::tagList(
      htmltools::p(paste0("Your overall score: ", total_score)),
      htmltools::p(paste0("Your score so far: ", score_so_far))
    )
  })
}

shinyApp(ui = ui, server = server)
TarJae commented 4 months ago

I have invited you to my franz-vokabel app. This is a reproducible example.

joemarlo commented 4 months ago

I took a look at your app and I'm not sure of the solution. My guess is that since you are bundling the image with the package itself, you'll need to use shiny::addResourcePath() to ensure the image file is available from the Shiny runtime.