Skip to content

Instantly share code, notes, and snippets.

@Ax3man
Last active January 31, 2020 18:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ax3man/532503ba333a5d9e2e619f4d33f796dd to your computer and use it in GitHub Desktop.
Save Ax3man/532503ba333a5d9e2e619f4d33f796dd to your computer and use it in GitHub Desktop.
# See gif at https://twitter.com/_Axeman_/status/1041286690357354496
library(tidyverse)
library(gganimate)
# This function does the basic clculations for a data.frame of circular coordinates
find_circular_coords <- function(speed, row, column) {
steps <- 300
data_frame(
time = 1:steps,
angle = rep(seq(0, 2*pi, length.out = steps / speed), times = speed),
x = cos(angle) * 0.6 + row * 2,
y = sin(angle) * 0.6 + column * 2,
)
}
# To calculate average colors trhough lab space
average_colors <- function(col1, col2) {
lab1 <- convertColor(t(col2rgb(col1)/256), 'sRGB', 'Lab')
lab2 <- convertColor(t(col2rgb(col2)/256), 'sRGB', 'Lab')
lab <- (lab1 + lab2) / 2
col <- as.list(convertColor(lab, 'Lab' , 'sRGB'))
do.call(rgb, col)
}
# First find the outside reference cicles, with different speeds
reference_circles <- bind_rows(
'r1' = find_circular_coords(1, 1, 2),
'r2' = find_circular_coords(2, 1, 3),
'r3' = find_circular_coords(3, 1, 4),
'r4' = find_circular_coords(4, 1, 5),
'r5' = find_circular_coords(5, 1, 6),
'c1' = find_circular_coords(1, 2, 1),
'c2' = find_circular_coords(2, 3, 1),
'c3' = find_circular_coords(3, 4, 1),
'c4' = find_circular_coords(4, 5, 1),
'c5' = find_circular_coords(5, 6, 1),
.id = 'circle'
)
# add colors
circle_info <- data_frame(
circle = c('r1', 'r2', 'r3', 'r4', 'r5', 'c1', 'c2', 'c3', 'c4', 'c5'),
color = rep(c('yellow', 'green', 'blue', 'purple', 'red'), 2)
)
reference_circles <- left_join(reference_circles, circle_info, by = "circle")
# Join the different combinations of outer circles together, to create the inner circles
inner_circles <- expand.grid(
row = paste0('r', 1:5),
column = paste0('c', 1:5),
stringsAsFactors = FALSE
) %>%
as_tibble() %>%
right_join(select(reference_circles, circle, time, y, color_x = color), by = c('row' = 'circle')) %>%
right_join(select(reference_circles, circle, time, x, color_y = color), by = c('column' = 'circle', 'time')) %>%
mutate(
circle = paste0(row, column),
color = map2_chr(color_x, color_y, average_colors)
)
# Make one big data.frame
combined <- bind_rows(reference_circles, inner_circles)
# Calculate the horizontal and vertical lines that connect the coordinates
hor_segments <- inner_circles %>%
filter(column == 'c5') %>%
select(row, column, x_end = x, y_end = y, time) %>%
left_join(
select(reference_circles, circle, x_start = x, y_start = y, time),
by = c('row' = 'circle', 'time')
) %>%
rename(circle = row)
ver_segments <- inner_circles %>%
filter(row == 'r5') %>%
select(row, column, x_end = x, y_end = y, time) %>%
left_join(
select(reference_circles, circle, x_start = x, y_start = y, time),
by = c('column' = 'circle', 'time')
) %>%
rename(circle = column)
segments <- bind_rows(hor_segments, ver_segments)
# Plot and animate
p <- ggplot(combined, aes(x, y, group = circle)) +
geom_path(aes(color = color), size = 1.5) +
geom_segment(
aes(x = x_start, xend = x_end, y = y_start, yend = y_end),
data = segments, lty = 2, color = 'grey80'
) +
geom_point(data = reference_circles, fill = 'white', color = 'black', shape = 21, size = 4) +
geom_point(data = inner_circles, color = 'black', size = 1.5) +
coord_equal() +
scale_y_reverse() +
scale_color_identity() +
transition_reveal(circle, time) +
ease_aes(default = 'linear') +
theme_void() +
theme(legend.position = 'none', plot.background = element_rect(fill = 'black'))
# Save the animation
anim_save(
'test.gif',
animate(p, 300, 30)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment