Last active
January 31, 2020 18:50
-
-
Save Ax3man/532503ba333a5d9e2e619f4d33f796dd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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