class: center, middle, inverse, title-slide # Easy Flipbook Recipes ## with {flipbookr} and {xaringan} ### Gina Reynolds, August 2020 --- class: inverse, center, middle # These slides are aimed at helping you get started making flipbooks with {flipbookr} and {xaringan}. --- class: inverse, center, middle # It will show you what's needed in your source .Rmd document... --- class: inverse, center, middle # ...and what to expect for the flipbooked result. --- class: inverse # In this guide: -- ##- slides with a *dark background* communicate about *'how-to'*, i.e. what will be in your .Rmd file -- ##- and slides with a *light background* demo the *flipbook experience* that you'll create upon 'knitting'. --- class: inverse # I assume that you are familiar with: ##- [the R programming language](https://www.r-project.org/) ##- [knitr and Rmarkdown](https://bookdown.org/yihui/rmarkdown/) which let you comingle prose and code, and compile to documents with prose, code, output and more! --- class: inverse ## If the {xaringan} package is new to you, things might feel a little more foreign. -- ## {xaringan} translates an Rmarkdown (.Rmd) file to an .html slide show. -- ## For background on {xaringan} you might first check out [an introduction](https://bookdown.org/yihui/rmarkdown/xaringan.html) and later come back to a [styling guide](https://arm.rbind.io/slides/xaringan.html#1) --- class: inverse, middle, center # Okay. --- class: inverse, middle, center # Ready to cook up some flipbooks? --- class: inverse, middle, center # Let's get started! --- class: inverse ## Step 0: Installing {xaringan} and {flipbookr} -- - ### In your R console: ```r install.packages("xaringan") install.packages("remotes") # allows you to install development packages from github remotes::install_github("EvaMaeRey/flipbookr") ``` -- - ### Note: you probably don't need to update dependency packages when installing {flipbookr}, i.e. select option #3, 'don't update' if prompted. -- - ### Restart R. -- - ### Congrats! The foundation is laid for flipbooking! --- class: inverse, middle, center # Step 1. Set up --- class: inverse ## 1a. In an .Rmd file, start with a YAML like this: ````markdown --- title: "My First Flipbook" subtitle: "With flipbookr and xaringan" author: "Your name here" output: xaringan::moon_reader: lib_dir: libs css: [default, hygge, ninjutsu] nature: ratio: 16:10 highlightStyle: github highlightLines: true countIncrementalSlides: false --- ```` -- ### This declares your output document to be an html {xaringan} slide show. --- class: inverse ## 1b. setup code chunk ````markdown ```{r setup, include = FALSE} library(flipbookr) library(tidyverse) knitr::opts_chunk$set(fig.width = 6, message = FALSE, warning = FALSE, comment = "", cache = F) ``` ```` -- ### Your setup code chunk loads {flipbookr}, and maybe other packages (like the {tidyverse} in this example) and sets some knitr defaults. --- class: inverse ## 1c. css code chunk ````markdown ```{css, eval = TRUE, echo = FALSE} .remark-code{line-height: 1.5; font-size: 80%} @media print { .has-continuation { display: block; } } ``` ```` -- ### css stands for cascading style sheets (you'll see that in the YAML too), and this code chunk helps define the look of the html document you'll ultimately produce. -- ### In this chunk, you can quickly adjust the font size for the code that you'll be revealing. Now it is set to 80%. --- class: inverse, middle, center # Step 2: building a code pipeline in a 'source' code chunk --- class: inverse ### A *source* code chunk, named 'my_cars' will serve as the material to be flipbooked. ````markdown ```{r my_cars, include = FALSE} cars %>% ggplot() + aes(x = speed) + aes(y = dist) + #BREAK geom_point( shape = 21, size = 7, #BREAK2 color = "magenta", #BREAK3 alpha = .8 #BREAK4 ) + #BREAK aes(fill = speed) + scale_fill_viridis_c() + theme_minimal() #BREAK ``` ```` -- #### We'll refer to this code chunk later. We don't want to see this chunk itself, so you should set `include = FALSE` --- class: inverse, middle, center # Step 3: Ask for flipbooked version of source code --- class: inverse ### In your .Rmd use the {flipbookr} function `chunk_reveal()` *inline* as follows. Refer to the source code chunk that you have prepared by name. ```markdown --- `r chunk_reveal(chunk_name = "my_cars", title = "### First flipbook!")` ``` -- ### Also, indicate you want a slide break before the inline code as shown above. The slide break is indicated with three dashes, '---' at the beginning of a line with no trailing spaces. -- ### Let's see the result... (you might 'knit' your .Rmd now) --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r *cars ``` ] .panel2-my_cars-auto[ ``` speed dist 1 4 2 2 4 10 3 7 4 4 7 22 5 8 16 6 9 10 7 10 18 8 10 26 9 10 34 10 11 17 11 11 28 12 12 14 13 12 20 14 12 24 15 12 28 16 13 26 17 13 34 18 13 34 19 13 46 20 14 26 21 14 36 22 14 60 23 14 80 24 15 20 25 15 26 26 15 54 27 16 32 28 16 40 29 17 32 30 17 40 31 17 50 32 18 42 33 18 56 34 18 76 35 18 84 36 19 36 37 19 46 38 19 68 39 20 32 40 20 48 41 20 52 42 20 56 43 20 64 44 22 66 45 23 54 46 24 70 47 24 92 48 24 93 49 24 120 50 25 85 ``` ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% * ggplot() ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_02_output-1.png" width="432" /> ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% ggplot() + * aes(x = speed) ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_03_output-1.png" width="432" /> ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% ggplot() + aes(x = speed) + * aes(y = dist) ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_04_output-1.png" width="432" /> ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + * geom_point( * shape = 21, * size = 7, * color = "magenta", * alpha = .8 * ) ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_05_output-1.png" width="432" /> ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, size = 7, color = "magenta", alpha = .8 ) + * aes(fill = speed) ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_06_output-1.png" width="432" /> ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, size = 7, color = "magenta", alpha = .8 ) + aes(fill = speed) + * scale_fill_viridis_c() ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_07_output-1.png" width="432" /> ] --- count: false ### First flipbook! .panel1-my_cars-auto[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, size = 7, color = "magenta", alpha = .8 ) + aes(fill = speed) + scale_fill_viridis_c() + * theme_minimal() ``` ] .panel2-my_cars-auto[ <img src="flipbook_recipes_files/figure-html/my_cars_auto_08_output-1.png" width="432" /> ] <style> .panel1-my_cars-auto { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-my_cars-auto { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-my_cars-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- class: inverse, center, middle # Step 4: Modify the recipe --- class: inverse ## We've looked at the *classic* flipbook recipe -- what `chunk_reveal()` gives us when basically use *defaults*. -- ## The classic flipbook is a side-by-side *code-output* reveal, where break points are determined *automatically*. `chunk_reveal()` pauses where parentheses are balanced at ends of lines. --- class: inverse ## Let's change the recipe. -- ### We get different build behavior by setting the `break_type` argument to `"user"`. We can refering to the same chunk, 'my_cars'. ```markdown --- `r chunk_reveal("my_cars", break_type = "user", title = "### Another code movie!")` ``` -- ### When break_type = "user", flipbookr's `chunk_reveal()` looks for the special comment *#BREAK* in the source code chunk, and displays code sequentially at the *user defined* breaks. -- ### Let's see the result... (you might 'knit' your .Rmd now) --- count: false ### Another code movie! .panel1-my_cars-user[ ```r *cars %>% * ggplot() + * aes(x = speed) + * aes(y = dist) ``` ] .panel2-my_cars-user[ <img src="flipbook_recipes_files/figure-html/my_cars_user_01_output-1.png" width="432" /> ] --- count: false ### Another code movie! .panel1-my_cars-user[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + * geom_point( * shape = 21, * size = 7, * color = "magenta", * alpha = .8 * ) ``` ] .panel2-my_cars-user[ <img src="flipbook_recipes_files/figure-html/my_cars_user_02_output-1.png" width="432" /> ] --- count: false ### Another code movie! .panel1-my_cars-user[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, size = 7, color = "magenta", alpha = .8 ) + * aes(fill = speed) + * scale_fill_viridis_c() + * theme_minimal() ``` ] .panel2-my_cars-user[ <img src="flipbook_recipes_files/figure-html/my_cars_user_03_output-1.png" width="432" /> ] <style> .panel1-my_cars-user { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-my_cars-user { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-my_cars-user { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- class: inverse ### Let's change the recipe again. Setting the `break_type` argument to `"non_seq"` allows you to define a non sequential order of display in the flipbook. ```markdown --- `r chunk_reveal("my_cars", break_type = "non_seq")` ``` -- ### Here the comments #BREAK2, #BREAK3 etc. in the 'my_cars' code chunk inform flipbookr of which lines of code should be displayed in which frames of the flipbook. Lines without such a comment are always displayed. -- ### Let's see the result ... --- count: false .panel1-my_cars-non_seq[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, ) + aes(fill = speed) + scale_fill_viridis_c() + theme_minimal() ``` ] .panel2-my_cars-non_seq[ <img src="flipbook_recipes_files/figure-html/my_cars_non_seq_01_output-1.png" width="432" /> ] --- count: false .panel1-my_cars-non_seq[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, * size = 7, ) + aes(fill = speed) + scale_fill_viridis_c() + theme_minimal() ``` ] .panel2-my_cars-non_seq[ <img src="flipbook_recipes_files/figure-html/my_cars_non_seq_02_output-1.png" width="432" /> ] --- count: false .panel1-my_cars-non_seq[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, size = 7, * color = "magenta", ) + aes(fill = speed) + scale_fill_viridis_c() + theme_minimal() ``` ] .panel2-my_cars-non_seq[ <img src="flipbook_recipes_files/figure-html/my_cars_non_seq_03_output-1.png" width="432" /> ] --- count: false .panel1-my_cars-non_seq[ ```r cars %>% ggplot() + aes(x = speed) + aes(y = dist) + geom_point( shape = 21, size = 7, color = "magenta", * alpha = .8 ) + aes(fill = speed) + scale_fill_viridis_c() + theme_minimal() ``` ] .panel2-my_cars-non_seq[ <img src="flipbook_recipes_files/figure-html/my_cars_non_seq_04_output-1.png" width="432" /> ] <style> .panel1-my_cars-non_seq { color: black; width: 38.6060606060606%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-my_cars-non_seq { color: black; width: 59.3939393939394%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-my_cars-non_seq { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- class: inverse ## The final recipe we'll look at is changing the `display_type` from its default, which is `c("code", "output")`. --- class: inverse ### Let's build a *new* source code chunk, "my_mtcars". ````markdown ```{r my_mtcars, include = F} mtcars %>% ggplot() + aes(x = factor(cyl)) + aes(y = mpg) + geom_boxplot() + geom_jitter(alpha = .5, width = .25) ``` ```` -- #### Then we use `chunk_reveal()` on this the "my_mtcars" code chunk and set display_type = "output" to give us *only the output panel*. ```markdown --- `r chunk_reveal("my_mtcars", display_type = "output")` ``` -- ### Let's look at the flipbook ... --- count: false ``` mpg cyl disp hp drat wt qsec vs am gear carb Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 ``` --- count: false <img src="flipbook_recipes_files/figure-html/my_mtcars_auto_02_output-1.png" width="432" /> --- count: false <img src="flipbook_recipes_files/figure-html/my_mtcars_auto_03_output-1.png" width="432" /> --- count: false <img src="flipbook_recipes_files/figure-html/my_mtcars_auto_04_output-1.png" width="432" /> --- count: false <img src="flipbook_recipes_files/figure-html/my_mtcars_auto_05_output-1.png" width="432" /> --- count: false <img src="flipbook_recipes_files/figure-html/my_mtcars_auto_06_output-1.png" width="432" /> --- count: false <img src="flipbook_recipes_files/figure-html/my_mtcars_auto_07_output-1.png" width="432" /> <style> .panel1-my_mtcars-auto { color: black; width: 99%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel2-my_mtcars-auto { color: black; width: NA%; hight: 32%; float: left; padding-left: 1%; font-size: 80% } .panel3-my_mtcars-auto { color: black; width: NA%; hight: 33%; float: left; padding-left: 1%; font-size: 80% } </style> --- class: inverse, # Congratulations! -- ### Now your are cooking with {flipbookr} and {xaringan}. We went through these steps: ###- Step 0: Install {flipbookr} and {xaringan} ###- Step 1: Set up .Rmd (a. YAML, b. setup code chunk, c. css code chunk) ###- Step 2: Write a source code to be flipbooked ###- Step 3: Use {flipbookr}'s chunk_reveal to build flipbook (upon knit) --- class: inverse, ## *And* you have learned *four flipbook recipes*! -- ###1. *The classic* (defaults code-output reveal at auto break points) -- ###2. *The picky eater* **break_type = "user", with #BREAK comments in source code chunk** user defines break points -- ###3. *Tossed salad* **break_type = "non_seq", with #BREAK2, #BREAK3 comments in source chunk** user sets order of break points, which may be non sequential -- ###2. *Hold the code* **display_type = "output"** display only an output panel --- class: inverse # Afterward: Source for a tiny flipbook and output ## You might find it useful to at an .Rmd for a full (but tiny) slide show with flipbooks and the resultant html. ##- [.Rmd](https://raw.githubusercontent.com/EvaMaeRey/flipbooks/master/tiny_flipbook.Rmd) ##- [.html](https://evamaerey.github.io/flipbooks/tiny_flipbook.html) --- class: inverse ## Epilogue: Share your work and learn more recipes ### Once you master flipbooking you'll probably want to share your work -- ### But the .html slides that {xaringan} produces aren't contained in a single file, so doing so can be a little tricky! -- ### Instead a folder of associated files will be created, and this needs to travel with your work. --- class: inverse ## Epilogue: Share your work and learn more recipes ### For more about ways to share your slide shows and for more flipbook recipes consult the template that travels with the {flipbookr} package. -- ### In RStudio access this .Rmd template via: File -> New File -> RMarkdown -> From Template -> A Minimal Flipbook -- ## You may check out the template rendered to html [here](https://evamaerey.github.io/flipbooks/flipbookr/skeleton.html). --- class: inverse # Acknowledgments ### Emi Tanaka and Garrick Aden-Buie were critical in getting this project off the ground and have provided much help, support and feedback in the development. ### Tidyverse tools, and especially ggplot2, have been an inspiration for flipbooks. ### The knitr/Rmarkdown ecosystem are {xaringan} are of course a key infrastructures this project relies on. --- class: inverse # Spread the word and giving feedback ### Please help us spread the word about flipbooks. Consider a quick acknowledgment like: *The 'flipbooked' portion of this presentation was created with the new {flipbookr} package. Get it at remotes::install_github("EvaMaeRey/flipbookr")* ### Feedback? Contributions? Leave an issue at: https://github.com/EvaMaeRey/flipbookr