我正在尝试在 R 中制作斐波那契数列的动画,其中正方形和螺旋线一起生长。我已经成功创建了两个单独的动画:
不断增长的正方形,但没有不断增长的螺旋: 正方形一一出现,但螺旋是静态的。
不断增长的螺旋,但没有不断增长的方块: 螺旋不断增长,但正方形是静止的。
我想将这两种效果组合在一个动画中,其中每个方块都以其相应的螺旋弧线出现。以下是我的尝试:
library(ggplot2)
library(gganimate)
# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
fib_seq <- numeric(n)
fib_seq[1] <- 1
fib_seq[2] <- 1
for (i in 3:n) {
fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
}
return(fib_seq)
}
# Function to generate quarter circle arc data
quarter_circle_arc <- function(x, y, size, direction) {
theta <- seq(0, pi/2, length.out = 100)
if (direction == 1) {
# Bottom-left arc
data.frame(
x = x + size * (1 - cos(theta)),
y = y + size * (1 - sin(theta))
)
} else if (direction == 2) {
# Bottom-right arc
data.frame(
x = x + size * (sin(theta) - 1) + size,
y = y + size * (1 - cos(theta))
)
} else if (direction == 3) {
# Top-right arc
data.frame(
x = x + size * (cos(theta) - 1) + size,
y = y + size * (sin(theta) - 1) + size
)
} else if (direction == 0) {
# Top-left arc
data.frame(
x = x + size * (1 - sin(theta)),
y = y + size * (cos(theta) - 1) + size
)
}
}
# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)
# Initialize the data frame for squares
squares <- data.frame(
x = numeric(10),
y = numeric(10),
size = fib_seq,
direction = numeric(10),
frame = 1:10
)
# Initialize the data frame for arcs
arcs <- data.frame(
x = numeric(0),
y = numeric(0),
frame = integer(0)
)
# Set the initial position and direction
x <- 0
y <- 0
direction <- 1
for (i in 1:10) {
if (direction == 1) {
y <- y - ifelse(x == 0, 0, fib_seq[i])
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 2) {
x <- x + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 3) {
x <- x - fib_seq[i-2]
y <- y + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 4) {
x <- x - fib_seq[i]
y <- y - fib_seq[i-2]
squares[i, "x"] <- x
squares[i, "y"] <- y
}
# Store the direction for the arcs
squares[i, "direction"] <- direction
# Generate the arc for the current square and append it to arcs data frame
new_arc <- quarter_circle_arc(
squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4)
)
new_arc$frame <- i # Assign the frame for animation
arcs <- rbind(arcs, new_arc)
# Update the direction
direction <- (direction %% 4) + 1
}
# Create the base plot
p <- ggplot() +
coord_fixed(ratio = 1) +
theme_void()
# Plot squares and arcs with gradual appearance
p_anim <- p +
geom_rect(data = squares, aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size, frame = frame),
fill = "white", color = "black") +
geom_path(data = arcs, aes(x = x, y = y, frame = frame), color = "black") +
transition_manual(frames = squares$frame, cumulative = TRUE) # Keep previous frames visible
# Render the animation
animate(p_anim, nframes = 100, fps = 10)
library(ggplot2)
library(gganimate)
# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
fib_seq <- numeric(n)
fib_seq[1] <- 1
fib_seq[2] <- 1
for (i in 3:n) {
fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
}
return(fib_seq)
}
# Function to generate quarter circle arc data
quarter_circle_arc <- function(x, y, size, direction) {
theta <- seq(0, pi/2, length.out = 100)
if (direction == 1) {
# Bottom-left arc
data.frame(
x = x + size * (1 - cos(theta)),
y = y + size * (1 - sin(theta))
)
} else if (direction == 2) {
# Bottom-right arc
data.frame(
x = x + size * (sin(theta) - 1) + size,
y = y + size * (1 - cos(theta))
)
} else if (direction == 3) {
# Top-right arc
data.frame(
x = x + size * (cos(theta) - 1) + size,
y = y + size * (sin(theta) - 1) + size
)
} else if (direction == 0) {
# Top-left arc
data.frame(
x = x + size * (1 - sin(theta)),
y = y + size * (cos(theta) - 1) + size
)
}
}
# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)
# Initialize the data frame for squares
squares <- data.frame(
x = numeric(10),
y = numeric(10),
size = fib_seq,
direction = numeric(10),
frame = 1:10
)
# Initialize the data frame for arcs
arcs <- data.frame(
x = numeric(0),
y = numeric(0),
frame = integer(0)
)
# Set the initial position and direction
x <- 0
y <- 0
direction <- 1
for (i in 1:10) {
if (direction == 1) {
y <- y - ifelse(x == 0, 0, fib_seq[i])
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 2) {
x <- x + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 3) {
x <- x - fib_seq[i-2]
y <- y + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 4) {
x <- x - fib_seq[i]
y <- y - fib_seq[i-2]
squares[i, "x"] <- x
squares[i, "y"] <- y
}
# Store the direction for the arcs
squares[i, "direction"] <- direction
# Generate the arc for the current square and append it to arcs data frame
new_arc <- quarter_circle_arc(
squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4)
)
new_arc$frame <- i # Assign the frame for animation
arcs <- rbind(arcs, new_arc)
# Update the direction
direction <- (direction %% 4) + 1
}
# Create the base plot
p <- ggplot() +
coord_fixed(ratio = 1) +
theme_void()
# Plot squares with gradual appearance
for (i in 1:10) {
p <- p +
geom_rect(data = squares[1:i,], aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size),
fill = "white", color = "black") +
geom_path(data = arcs[arcs$frame <= i,],
aes(x = x, y = y), color = "black")
}
# Animate the plot with growing spiral and preserving squares
p_anim <- p +
transition_reveal(arcs$frame) +
enter_fade() +
exit_fade()
# Render the animation
animate(p_anim, nframes = 100, fps = 10)
我希望正方形与相应的弧线一起逐渐出现,形成不断增长的螺旋。然而,我还没能实现这一目标。
library(ggplot2)
library(gganimate)
# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
fib_seq <- numeric(n)
fib_seq[1] <- 1
fib_seq[2] <- 1
for (i in 3:n) {
fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
}
return(fib_seq)
}
# Function to generate quarter circle arc data
quarter_circle_arc <- function(x, y, size, direction) {
theta <- seq(0, pi/2, length.out = 100)
if (direction == 1) {
# Bottom-left arc
data.frame(
x = x + size * (1 - cos(theta)),
y = y + size * (1 - sin(theta))
)
} else if (direction == 2) {
# Bottom-right arc
data.frame(
x = x + size * (sin(theta) - 1) + size,
y = y + size * (1 - cos(theta))
)
} else if (direction == 3) {
# Top-right arc
data.frame(
x = x + size * (cos(theta) - 1) + size,
y = y + size * (sin(theta) - 1) + size
)
} else if (direction == 0) {
# Top-left arc
data.frame(
x = x + size * (1 - sin(theta)),
y = y + size * (cos(theta) - 1) + size
)
}
}
# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)
# Initialize the data frame for squares
squares <- data.frame(
x = numeric(10),
y = numeric(10),
size = fib_seq,
direction = numeric(10),
frame = 1:10
)
# Initialize the data frame for arcs
arcs <- data.frame(
x = numeric(0),
y = numeric(0),
frame = integer(0)
)
# Set the initial position and direction
x <- 0
y <- 0
direction <- 1
for (i in 1:10) {
if (direction == 1) {
y <- y - ifelse(x == 0, 0, fib_seq[i])
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 2) {
x <- x + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 3) {
x <- x - fib_seq[i-2]
y <- y + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 4) {
x <- x - fib_seq[i]
y <- y - fib_seq[i-2]
squares[i, "x"] <- x
squares[i, "y"] <- y
}
# Store the direction for the arcs
squares[i, "direction"] <- direction
# Generate the arc for the current square and append it to arcs data frame
new_arc <- quarter_circle_arc(
squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4)
)
new_arc$frame <- i # Assign the frame for animation
arcs <- rbind(arcs, new_arc)
# Update the direction
direction <- (direction %% 4) + 1
}
# Create the base plot
p <- ggplot() +
coord_fixed(ratio = 1) +
theme_void()
p <- p +
geom_rect(
data = squares, aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size),
fill = "white", color = "black"
) +
geom_path(
data = arcs,
aes(x = x, y = y), color = "black"
)
# Animate the plot with growing spiral and preserving squares
p_anim <- p +
transition_manual(frames = frame, cumulative = TRUE) + # Keep previous frames visible
enter_fade() +
exit_fade()
# Render the animation
animate(p_anim, nframes = 100, fps = 10)