I wanted to try animating Truchet tiles after seeing some really cool examples (see: https://twitter.com/Eko3316/status/1487367084292157448).
I will use this packages:
library(gganimate) library(sf) library(tidyverse) library(truchet)
Create a function to rotate a tile:
rotation = function(a, x, y, type){ tile <- st_truchet_p(type = type) rm <- matrix(c(cos(a), sin(a), -sin(a), cos(a)), nrow = 2, ncol = 2) tile %>% mutate(geometry = st_geometry(tile) * rm + c(x, y)) %>% st_sf() }
Prepare the moving tile(s):
a <- c(seq(0, pi/2, pi/90), rep(pi/2, 60), seq(pi/2, pi, pi/90), rep(pi, 60), seq(pi, 3 * pi/2, pi/90), rep(3 * pi/2, 60), seq(3 * pi/2, 2 * pi, pi/90), rep(2 * pi, 60)) tile_1 <- data.frame() count <- 0 for(i in a){ count <- count +1 df <- rbind(tile_1, data.frame(rotation(a = i, x = 1, y = 1, type = "dr"), state = count)) } tile_1 <- tile_1 %>% st_sf() tile_2 <- data.frame() count <- 0 for(i in a){ count <- count +1 df <- rbind(tile_2, data.frame(rotation(a = i, x = 2, y = 2, type = "dr"), state = count)) } tile_2 <- tile_2 %>% st_sf()
Rest of mosaic:
xlim <- c(1, 2) ylim <- c(1, 2) # Create a data frame with the spots for tiles container <- expand.grid(x = seq(xlim[1], xlim[2], 1), y = seq(ylim[1], ylim[2], 1)) %>% #filter(x != 0 | y != 0) %>% mutate(tiles = sample(c("dr", "fne", "fse", "dr"), n(), replace = TRUE), scale_p = 1)
Assemble mosaic:
mosaic <- st_truchet_ms(df = container)
Create plot and render:
p <- ggplot() + geom_sf(data = mosaic, aes(fill = factor(color)), color = NA) + geom_sf(data = df %>% st_sf(), aes(fill = factor(color), group = state), color = NA) + scale_fill_manual(values = c("1" = "#0057b7", "2" = "#ffd700")) + #values = c("black", "white")) + theme_void() + theme(legend.position = "none") + transition_time(state) animate(p, rewind = FALSE, fps = 60, duration = 10, res = 300, height = 2, width = 2, units = "in")
Save plot:
anim_save("animated-mosaic.gif")
Create plot and render:
p <- ggplot() + geom_sf(data = mosaic, aes(fill = factor(color)), color = NA) + geom_sf(data = df %>% st_sf(), aes(fill = factor(color), group = state), color = NA) + scale_fill_manual(values = c("white", "black")) + theme_void() + theme(legend.position = "none") + transition_time(state) animate(p, rewind = TRUE, fps = 60, duration = 10, res = 300, height = 2, width = 2, units = "in")
Save plot:
anim_save("animated-mosaic-b.gif")
Moving tile(s):
a <- c(seq(0, pi/2, pi/90), rep(pi/2, 60), seq(pi/2, pi, pi/90), rep(pi, 60), seq(pi, 3 * pi/2, pi/90), rep(3 * pi/2, 60), seq(3 * pi/2, 2 * pi, pi/90), rep(2 * pi, 60)) df <- data.frame() count <- 0 for(i in a){ count <- count +1 df <- rbind(df, data.frame(rotation(a = i, x = 3, y = 3, type = "dl"), state = count)) } df <- df %>% st_sf()
Rest of tiles:
xlim <- c(0, 6) ylim <- c(0, 6) # Create a data frame with the spots for tiles container <- expand.grid(x = seq(xlim[1], xlim[2], 1), y = seq(ylim[1], ylim[2], 1)) %>% dplyr::filter(x != 3 | y != 3) %>% mutate(tiles = sample(c("fnw", "-", "fse", "|"), n(), replace = TRUE), scale_p = sample(c(1, 1/2), n(), replace = TRUE))
Assemble mosaic:
mosaic <- st_truchet_ms(df = container)
Plot and render:
p <- ggplot() + geom_sf(data = mosaic, aes(fill = factor(color)), color = NA) + geom_sf(data = df %>% st_sf(), aes(fill = factor(color), group = state), color = NA) + scale_fill_manual(values = c("black", "white")) + theme_void() + theme(legend.position = "none") + transition_time(state) animate(p, rewind = TRUE, fps = 60, duration = 10, res = 300, height = 2, width = 2, units = "in")
Save animation:
anim_save("animated-mosaic-2.gif")
Plot and render:
p <- ggplot() + geom_sf(data = mosaic, aes(fill = factor(color)), color = NA) + geom_sf(data = df %>% st_sf(), aes(fill = factor(color), group = state), color = NA) + scale_fill_manual(values = c("white", "black")) + theme_void() + theme(legend.position = "none") + transition_time(state) animate(p, rewind = TRUE, fps = 60, duration = 10, res = 300, height = 2, width = 2, units = "in")
Save animation:
anim_save("animated-mosaic-2-b.gif")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.