class: inverse <style type="text/css"> /* custom.css */ .left-code { color: #777; width: 48%; height: 92%; float: left; } .right-plot { width: 50%; float: right; padding-left: 1%; } </style> .title[gganimate] .sticker-float[![gganimate](resources/gganimate.png)] ## The grammar of animation .bottom[ ### Mitchell O'Hara-Wild (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@mitchoharawild](https://twitter.com/mitchoharawild)) ### Ursula Laa (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@UschiLaa](https://twitter.com/UschiLaa/)) ### Nicholas Spyrison (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@nspyrison](https://twitter.com/nspyrison/)) ### 22 March 2019 ### Slides @ [mitchelloharawild.com/wombat-gganimate](https://mitchelloharawild.com/wombat-gganimate) ] --- class: inverse --- class: inverse .animated.rubberBand.title[gganimate] .sticker-float[![gganimate](resources/gganimate.png)] --- class: inverse .title[gganimate] .sticker-float[![gganimate](resources/gganimate.png)] .animated.rubberBand[ .desc[The grammar of animation] ] --- class: inverse .title[gganimate] .sticker-float[![gganimate](resources/gganimate.png)] .desc[The grammar of animation] .bottom[ .animated.zoomInDown[ ### Mitchell O'Hara-Wild (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@mitchoharawild](https://twitter.com/mitchoharawild)) ### Ursula Laa (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@UschiLaa](https://twitter.com/UschiLaa/)) ### Nicholas Spyrison (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@nspyrison](https://twitter.com/nspyrison/)) ### ### ] ] --- class: inverse .title[gganimate] .sticker-float[![gganimate](resources/gganimate.png)] .desc[The grammar of animation] .bottom[ ### Mitchell O'Hara-Wild (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@mitchoharawild](https://twitter.com/mitchoharawild)) ### Ursula Laa (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@UschiLaa](https://twitter.com/UschiLaa/)) ### Nicholas Spyrison (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@nspyrison](https://twitter.com/nspyrison/)) .animated.bounceInRight[ ### 22 March 2019 ### Slides @ [mitchelloharawild.com/wombat-gganimate](https://mitchelloharawild.com/wombat-gganimate) ] ] --- class: inverse .animated.hinge.title[gganimate] .animated.hinge.sticker-float[![gganimate](resources/gganimate.png)] .animated.hinge[ .desc[The grammar of animation] ] .animated.hinge.bottom[ ### Mitchell O'Hara-Wild (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@mitchoharawild](https://twitter.com/mitchoharawild)) ### Ursula Laa (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@UschiLaa](https://twitter.com/UschiLaa/)) ### Nicholas Spyrison (<svg style="height:0.8em;top:.04em;position:relative;fill:#1da1f2;" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>[@nspyrison](https://twitter.com/nspyrison/)) ### 22 March 2019 ### Slides @ [mitchelloharawild.com/wombat-gganimate](https://mitchelloharawild.com/wombat-gganimate) ] ] --- ## What is `gganimate`? .pull-left[ An extension to the grammar of graphics for animation. Specifically allows animations to be added to ggplot2 using a grammar of animation. ] .pull-right[
] --- ## Brief history of `gganimate` .pull-left[ .rounded-circle[![David Robinson](resources/david.jpeg)] Author: David Robinson. Primarily developed in 2016. Interface featured frame-by-frame animation building. ] .pull-right[ ![Thomas Lin Pedersen](resources/thomas.jpeg) Author: Thomas Lin Pedersen. Reimagined between 2017 and 2018. Re-built completely to support a grammar of animation with smooth transitions. ] --- class: center ## Why should I animate? <hr> ### Improves graphical re-orientation in time and space. <br> -- ### More compact delivery of information. <br> -- ### Allows for guided exploration of data, great for talks. <br> -- .animated.bounceIn[ ### Attention grabbing. #### (Tired students? Zzz...) ] --- ## Considerations in making effective animations <hr> ### Pace: speed of animation Quick animations may be hard to follow. Slow animations are boring and tedious. -- ### Perplex: amount of information It is easy for animations to be overwhelming and confusing. Multiple simple animations can be easier to digest. -- ### Purpose: Usefulness of using animation Is animation needed? Does it provide additional value? --- ## Usefulness of animation ### Static <img src="figure/ts-static-1.png" style="display: block; margin: auto;" /> --- ## Usefulness of animation ### Static <img src="figure/ts-static-zoom-1.png" style="display: block; margin: auto;" /> --- ## Usefulness of animation ### Animated
--- ## Usefulness of animation ### Animated
--- ## Usefulness of animation ### Interactive <iframe src="resources/electricity_plotly.html" width = "1000px", height = "400px" seamless="seamless" frameBorder="0"></iframe> --- ## Usefulness of animation ### Static <img src="figure/bc-static-1.png" style="display: block; margin: auto;" /> --- ## Usefulness of animation ### Animated <img src="figure/bc-anim-1.gif" style="display: block; margin: auto;" /> --- ## Usefulness of animation ### Interactive <iframe src="https://ebsmonash.shinyapps.io/gganimateBoxCox/?showcase=0" width="100%" height="650px"></iframe> --- class: inverse, center, middle .sticker-float[![gganimate](resources/gganimate.png)] .title[Your turn] # Think how you can use animations --- ## The basis - ggplot2 <hr> <br> > a system for declaratively creating graphics, based on "The Grammar of Graphics" Based on three simple concepts: * __Data__: input data should be formated in a data frame, where each column is a variable, and each row is an observation * __Mapping__: declaring a mapping of input data variables onto aestetics * __geoms__: the graphical primitives, e.g. geom_line, geom_point --- ## Basic workflow <hr> <br> <br> -- ### Initialise a ggplot by passing in data and mapping -- ### Add layers with graphical primitives (geoms) -- ### Add formatting specifications -- ### Add animation specifications <br> -- ### Let's try some simple examples! --- ## A simple example ### Using the economics dataset Let's start by passing the data to ggplot .left-code[ ```r *ggplot(economics) ``` ] .right-plot[ <img src="figure/output1-1.png" style="display: block; margin: auto;" /> ] --- ## A simple example ### Using the economics dataset The next step is to add the mapping .left-code[ ```r ggplot(economics) + * aes(date, unemploy) ``` ] .right-plot[ <img src="figure/output2-1.png" style="display: block; margin: auto;" /> ] --- ## A simple example ### Using the economics dataset Now we can add a graphical primitive, let's try a scatter plot .left-code[ ```r ggplot(economics) + aes(date, unemploy) + * geom_point() ``` ] .right-plot[ <img src="figure/output3-1.png" style="display: block; margin: auto;" /> ] --- ## A simple example ### Using the economics dataset Actually a line graph is better suited in this case .left-code[ ```r ggplot(economics) + aes(date, unemploy) + * geom_line() ``` ] .right-plot[ <img src="figure/output4-1.png" style="display: block; margin: auto;" /> ] --- ## A simple example ### Using the economics dataset Just one extra line turns this into an animation! .left-code[ ```r ggplot(economics) + aes(date, unemploy) + geom_line() + * transition_reveal(date) ``` ] .right-plot[ <img src="figure/output5-anim-1.gif" style="display: block; margin: auto;" /> ] --- ## A not-so-simple example, the datasaurus dozen Again, we first pass in the dataset to ggplot .left-code[ ```r *ggplot(datasaurus_dozen) ``` ] .right-plot[ <img src="figure/output5-1.png" style="display: block; margin: auto;" /> ] --- ## A not-so-simple example, the datasaurus dozen For each dataset we have x and y values, in addition we can map dataset to color .left-code[ ```r ggplot(datasaurus_dozen) + * aes(x, y, color=dataset) ``` ] .right-plot[ <img src="figure/output6-1.png" style="display: block; margin: auto;" /> ] --- ## A not-so-simple example, the datasaurus dozen Trying a simple scatter plot first, but there is too much information .left-code[ ```r ggplot(datasaurus_dozen) + aes(x, y, color=dataset) + * geom_point() ``` ] .right-plot[ <img src="figure/output7-1.png" style="display: block; margin: auto;" /> ] --- ## A not-so-simple example, the datasaurus dozen We can use facets to split up by dataset, revealing the different distributions .left-code[ ```r ggplot(datasaurus_dozen) + aes(x, y, color=dataset) + geom_point() + * facet_wrap(~dataset) ``` ] .right-plot[ <img src="figure/output8-1.png" style="display: block; margin: auto;" /> ] --- ## A not-so-simple example, the datasaurus dozen We can just as easily turn it into an animation, transitioning between dataset states! .left-code[ ```r ggplot(datasaurus_dozen) + aes(x, y) + geom_point() + * transition_states(dataset, 3, 1) + * labs(title = "Dataset: {closest_state}") ``` ] .right-plot[ <img src="figure/output9-1.gif" style="display: block; margin: auto;" /> ] --- class: inverse, middle .sticker-float[![gganimate](resources/gganimate.png)] # The grammar of animation <hr> ### Controlling plot movement with: - ### Transitions - ### Views - ### Shadows - ### Entrances/Exits - ### Easing --- ## Transitions How the data changes through the animation. <table class="table" style="font-size: 26px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Function </th> <th style="text-align:left;"> Description </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> transition_manual </td> <td style="text-align:left;"> Build an animation frame by frame (no tweening applied). </td> </tr> <tr> <td style="text-align:left;"> transition_states </td> <td style="text-align:left;"> Transition between frames of a plot (like moving between facets). </td> </tr> <tr> <td style="text-align:left;"> transition_time </td> <td style="text-align:left;"> Like transition_states, except animation pacing respects time. </td> </tr> <tr> <td style="text-align:left;"> transition_components </td> <td style="text-align:left;"> Independent animation of plot elements (by group). </td> </tr> <tr> <td style="text-align:left;"> transition_reveal </td> <td style="text-align:left;"> Gradually extends the data used to reveal more information. </td> </tr> <tr> <td style="text-align:left;"> transition_layers </td> <td style="text-align:left;"> Animate the addition of layers to the plot. Can also remove layers. </td> </tr> <tr> <td style="text-align:left;"> transition_filter </td> <td style="text-align:left;"> Transition between a collection of subsets from the data. </td> </tr> <tr> <td style="text-align:left;"> transition_events </td> <td style="text-align:left;"> Define entrance and exit times of each visual element (row of data). </td> </tr> </tbody> </table> --- ## Transitions Which transition was used in the following animations? .pull-left[ <img src="figure/transition-layers-1.gif" style="display: block; margin: auto;" /> ] -- .pull-right[ `transition_layers()` New layers are being added (and removed) over the dots. ] -- <hr> .pull-right[ ![](resources/tile-mean.gif) ] -- .pull-left[ `transition_manual()` No tweening is evident between frames, highlighting the discrete nature of the tiling function. ] --- ## Views How the plot window changes through the animation. <table class="table" style="font-size: 26px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Function </th> <th style="text-align:left;"> Description </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> view_follow </td> <td style="text-align:left;"> Change the view to follow the range of current data. </td> </tr> <tr> <td style="text-align:left;"> view_step </td> <td style="text-align:left;"> Similar to view_follow, except the view is static between transitions. </td> </tr> <tr> <td style="text-align:left;"> view_step_manual </td> <td style="text-align:left;"> Same as view_step, except view ranges are manually defined. </td> </tr> <tr> <td style="text-align:left;"> view_zoom </td> <td style="text-align:left;"> Similar to view_step, but appears smoother by zooming out then in. </td> </tr> <tr> <td style="text-align:left;"> view_zoom_manual </td> <td style="text-align:left;"> Same as view_zoom, except view ranges are manually defined. </td> </tr> </tbody> </table> --- ## Views Which view was used in the following animations? .pull-left[
] -- .pull-right[ `view_step_manual()` The view is changed without modifying the data. You can see the lines are shown without margins. ] -- <hr> .pull-right[ <img src="figure/view-follow-1.gif" style="display: block; margin: auto;" /> ] -- .pull-left[ `view_follow()` Plot axis follows the range of the data. ] --- ## Shadows How the history of the animation is shown. Useful to indicate speed of changes. <table class="table" style="font-size: 26px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Function </th> <th style="text-align:left;"> Description </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> shadow_mark </td> <td style="text-align:left;"> Previous (and/or future) frames leave permananent background marks. </td> </tr> <tr> <td style="text-align:left;"> shadow_trail </td> <td style="text-align:left;"> Similar to shadow_mark, except marks are from tweened data. </td> </tr> <tr> <td style="text-align:left;"> shadow_wake </td> <td style="text-align:left;"> Shows a shadow which diminishes in size and/or opacity over time. </td> </tr> </tbody> </table> --- ## Shadows Which shadow was used in the following animations? .pull-left[ <img src="figure/shadow-wake-1.gif" style="display: block; margin: auto;" /> ] -- .pull-right[ `shadow_wake()` The older tails of the points shrink in size, leaving a "wake" behind it. ] -- <hr> .pull-right[ <img src="figure/shadow-mark-1.gif" style="display: block; margin: auto;" /> ] -- .pull-left[ `shadow_mark()` Permanent marks are left by previous points in the animation. ] --- ## Entrances and exits How elements of the plot appear and disappear. <table class="table" style="font-size: 26px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Function </th> <th style="text-align:left;"> Description </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> enter_appear/exit_disappear </td> <td style="text-align:left;"> Poof! Instantly appears or disappears. </td> </tr> <tr> <td style="text-align:left;"> enter_fade/exit_fade </td> <td style="text-align:left;"> Opacity is used to fade in or out the elements. </td> </tr> <tr> <td style="text-align:left;"> enter_grow/exit_shrink </td> <td style="text-align:left;"> Element size will grow from or shrink to zero. </td> </tr> <tr> <td style="text-align:left;"> enter_recolour/exit_recolour </td> <td style="text-align:left;"> Change element colours to blend into the background. </td> </tr> <tr> <td style="text-align:left;"> enter_fly/exit_fly </td> <td style="text-align:left;"> Elements will move from/to a specific x,y position. </td> </tr> <tr> <td style="text-align:left;"> enter_drift/exit_drift </td> <td style="text-align:left;"> Elements will shift relative from/to their x,y position. </td> </tr> <tr> <td style="text-align:left;"> enter_reset/exit_reset </td> <td style="text-align:left;"> Clear all previously added entrace/exits. </td> </tr> </tbody> </table> --- ## Animation controls How data moves from one position to another. ```r p + ease_aes({aesthetic} = {ease}) p + ease_aes(x = "cubic") ``` [![ease examples](resources/ease.png)](https://easings.net/) .footnote[ Source: https://easings.net/ ] --- class: inverse, center, middle .sticker-float[![gganimate](resources/gganimate.png)] .title[Your turn] # Making the gapminder animation <iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/jbkSRLYSojo?rel=0&start=240" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- ## Making the gapminder animation ### Load the data and set the theme .left-code[ ```r *library(gapminder) *theme_set(theme_bw()) ``` ] .right-plot[ ] --- ## Making the gapminder animation ### Define the aesthetics .left-code[ ```r library(gapminder) theme_set(theme_bw()) *ggplot(gapminder) + * aes(x = gdpPercap, y=lifeExp, * size = pop, colour = country) ``` ] .right-plot[ <img src="figure/gm_output2-1.png" style="display: block; margin: auto;" /> ] --- ## Making the gapminder animation ### The plot is feeling a bit pointless... .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + * geom_point(show.legend = FALSE) ``` ] .right-plot[ <img src="figure/gm_output3-1.png" style="display: block; margin: auto;" /> ] --- ## Making the gapminder animation ### Transform the axis .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + * scale_x_log10() ``` ] .right-plot[ <img src="figure/gm_output4-1.png" style="display: block; margin: auto;" /> ] --- ## Making the gapminder animation ### Customise the colour and size of points .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + scale_x_log10() + * scale_color_viridis_d() + * scale_size(range = c(2, 12)) ``` ] .right-plot[ <img src="figure/gm_output5-1.png" style="display: block; margin: auto;" /> ] --- ## Making the gapminder animation ### Add some labels .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + scale_x_log10() + scale_color_viridis_d() + scale_size(range = c(2, 12)) + * labs(x = "GDP per capita", y = "Life expectancy") ``` ] .right-plot[ <img src="figure/gm_output7-1.png" style="display: block; margin: auto;" /> ] --- ## Making the gapminder animation ### Time to animate! ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country)) + geom_point(show.legend = FALSE) + scale_x_log10() + scale_color_viridis_d() + scale_size(range = c(2, 12)) + labs(x = "GDP per capita", y = "Life expectancy") + * ??? ``` -- What are appropriate some appropriate animation features? -- .pull-left[ - Transitions? - Views? ] .pull-right[ - Entrances/Exits? - Shadows? ] --- ## Transition with time: animating over year .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + scale_x_log10() + scale_color_viridis_d() + scale_size(range = c(2, 12)) + labs(x = "GDP per capita", y = "Life expectancy") + * transition_time(year) + * labs(title = "Year: {frame_time}") ``` ] .right-plot[ <img src="figure/gm_output2-1.gif" style="display: block; margin: auto;" /> ] --- ## Changing the view: scaling the y-axis to the data .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + scale_x_log10() + scale_color_viridis_d() + scale_size(range = c(2, 12)) + labs(x = "GDP per capita", y = "Life expectancy") + transition_time(year) + labs(title = "Year: {frame_time}") + * view_follow(fixed_y = TRUE) ``` ] .right-plot[ <img src="figure/gm_output3-1.gif" style="display: block; margin: auto;" /> ] -- Does this add value to the animation? --- ## Shadow the past: highlight the rate of change .left-code[ ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + scale_x_log10() + scale_color_viridis_d() + scale_size(range = c(2, 12)) + labs(x = "GDP per capita", y = "Life expectancy") + transition_time(year) + labs(title = "Year: {frame_time}") + * shadow_wake(wake_length = 0.1, alpha = FALSE) ``` ] .right-plot[ <img src="figure/gm_output4a-1.gif" style="display: block; margin: auto;" /> ] Can you see countries that move rapidly? --- ## Add your own flavour! ```r library(gapminder) theme_set(theme_bw()) ggplot(gapminder) + aes(x = gdpPercap, y=lifeExp, size = pop, colour = country) + geom_point(show.legend = FALSE) + scale_x_log10() + scale_color_viridis_d() + scale_size(range = c(2, 12)) + labs(x = "GDP per capita", y = "Life expectancy") + transition_time(year) + labs(title = "Year: {frame_time}") ``` - transition_*() family - view_*() family - shadow_*() family - ggplot2 changes --- ## Exporting animations ```r anim_save( filename = "./images/MyAnim.gif", animation = MyAnim, start_pause = 15, width = 480, height = 480, res = 150) ``` <img src="./resources/DIS_mt.gif" width="40%" height="40%" style="display: block; margin: auto;" /> --- ## Exporting animations ### Renderer options <table class="table" style="font-size: 26px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> Function </th> <th style="text-align:left;"> Description </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> gifski_renderer </td> <td style="text-align:left;"> Default, super fast gif renderer. </td> </tr> <tr> <td style="text-align:left;"> magick_renderer </td> <td style="text-align:left;"> Somewhat slower gif renderer. </td> </tr> <tr> <td style="text-align:left;"> ffmpeg_renderer </td> <td style="text-align:left;"> Uses ffmpeg to create a video from the animation. </td> </tr> <tr> <td style="text-align:left;"> av_renderer </td> <td style="text-align:left;"> Uses the av package to create a video (using ffmpeg). </td> </tr> <tr> <td style="text-align:left;"> file_renderer </td> <td style="text-align:left;"> Dumps a list of image frames from the animation. </td> </tr> <tr> <td style="text-align:left;"> sprite_renderer </td> <td style="text-align:left;"> Creates a spritesheet from frames of the animation. </td> </tr> </tbody> </table> --- class: inverse, center, middle .sticker-float[![gganimate](resources/gganimate.png)] .title[Your turn] # Make your own animation --- ## Simple alternative: Plotly <hr> We can also use plotly to easily make simple animations via ggplotly and the frames argument .left-code[ ```r library(plotly) p <- ggplot(datasaurus_dozen) + aes(x, y, frame = dataset) + geom_point() ggplotly(p) ``` More complicated alternative: use plotly directly (or basic libraries like D3.js) to have more control over the animation details, and e.g. embed them in a Shiny app. ] .right-plot[
] --- class: center ## Other animation libraries to check out <br> ### [D3.js](https://d3js.org/) ### [Vega](https://vega.github.io/vega/) / [Vega-lite](https://vega.github.io/vega-lite/) ### [Highcharts](https://www.highcharts.com/) ### [Bokeh](https://bokeh.pydata.org/en/latest/) ### [Seaborn](https://seaborn.pydata.org/) <br> This is not exhaustive - there are a lot of animation libraries! --- class: inverse, top .sticker-float[![gganimate](resources/gganimate.png)] .title[Thanks! <svg style="height:0.8em;top:.04em;position:relative;fill:white;" viewBox="0 0 576 512"><path d="M416 192c0-88.4-93.1-160-208-160S0 103.6 0 192c0 34.3 14.1 65.9 38 92-13.4 30.2-35.5 54.2-35.8 54.5-2.2 2.3-2.8 5.7-1.5 8.7S4.8 352 8 352c36.6 0 66.9-12.3 88.7-25 32.2 15.7 70.3 25 111.3 25 114.9 0 208-71.6 208-160zm122 220c23.9-26 38-57.7 38-92 0-66.9-53.5-124.2-129.3-148.1.9 6.6 1.3 13.3 1.3 20.1 0 105.9-107.7 192-240 192-10.8 0-21.3-.8-31.7-1.9C207.8 439.6 281.8 480 368 480c41 0 79.1-9.2 111.3-25 21.8 12.7 52.1 25 88.7 25 3.2 0 6.1-1.9 7.3-4.8 1.3-2.9.7-6.3-1.5-8.7-.3-.3-22.4-24.2-35.8-54.5z"/></svg>] <br> .larger[ <svg style="height:0.8em;top:.04em;position:relative;fill:white;" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg> Learn more on GitHub: [thomasp85/gganimate](https://github.com/thomasp85/gganimate) <svg style="height:0.8em;top:.04em;position:relative;fill:white;" viewBox="0 0 640 512"><path d="M640 51.2l-.3 12.2c-28.1.8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3.3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4.2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5.3v13.1c-19.4.6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4.3-3.6 0-10.3.3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5.8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1.2.5z"/></svg> More examples on the wiki: [thomasp85/gganimate/wiki](https://github.com/thomasp85/gganimate/wiki) <svg style="height:0.8em;top:.04em;position:relative;fill:white;" viewBox="0 0 576 512"><path d="M528 0H48C21.5 0 0 21.5 0 48v320c0 26.5 21.5 48 48 48h192l-16 48h-72c-13.3 0-24 10.7-24 24s10.7 24 24 24h272c13.3 0 24-10.7 24-24s-10.7-24-24-24h-72l-16-48h192c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zm-16 352H64V64h448v288z"/></svg> Review slides: [mitchelloharawild.com/wombat-gganimate](https://mitchelloharawild.com/wombat-gganimate) <br> .footnote[This work is licensed as <svg style="height:0.8em;top:.04em;position:relative;fill:white;" viewBox="0 0 496 512"><path d="M254.8 214.8l-33.2 17.3c-9.4-19.6-25.2-19.9-27.5-19.9-22.1 0-33.2 14.6-33.2 43.8 0 23.6 9.2 43.8 33.2 43.8 14.5 0 24.7-7.1 30.6-21.3l30.6 15.5c-6.2 11.5-25.7 39-65.1 39-22.6 0-74-10.3-74-77.1 0-58.7 43-77.1 72.6-77.1 30.8.2 52.7 12.1 66 36zm143.1 0l-32.8 17.3c-9.5-19.8-25.7-19.9-27.9-19.9-22.1 0-33.2 14.6-33.2 43.8 0 23.6 9.2 43.8 33.2 43.8 14.5 0 24.6-7.1 30.5-21.3l31 15.5c-2.1 3.7-21.4 39-65.1 39-22.7 0-74-9.9-74-77.1 0-58.7 43-77.1 72.6-77.1 30.8.2 52.7 12.1 65.7 36zM247.6 8C389.4 8 496 118.1 496 256c0 147.1-118.5 248-248.4 248C113.6 504 0 394.5 0 256 0 123.1 104.7 8 247.6 8zm.8 44.7C130.2 52.7 44.7 150.6 44.7 256c0 109.8 91.2 202.8 203.7 202.8 103.2 0 202.8-81.1 202.8-202.8.1-113.8-90.2-203.3-202.8-203.3z"/></svg> BY-NC 4.0.] ]