-
if we want to change the line’s shape based on time,we can use @lift to track the time, like this:
time = Observable(0.0)
xs = range(0, 7, length=40)
ys_1 = @lift(sin.(xs .- $time)) # if I change this to `ys_1 = sin.(xs.-time[])`,this line can't move
ys_2 = @lift(cos.(xs .- $time) .+ 3)
fig = lines(xs, ys_1, color = :blue, linewidth = 4,
axis = (title = @lift("t = $(round($time, digits = 1))"),))
scatter!(xs, ys_2, color = :red, markersize = 15)
framerate = 30
timestamps = range(0, 2, step=1/framerate)
record(fig, "time_animation.mp4", timestamps;
framerate = framerate) do t
time[] = t
end
-
but when we appending data to a plot,we don’t need @lift,we can do like this:
points = Observable(Point2f[(0, 0)])
fig, ax = scatter(points)
limits!(ax, 0, 30, 0, 30)
frames = 1:30
record(fig, "append_animation.mp4", frames;
framerate = 30) do frame
new_point = Point2f(frame, frame)
points[] = push!(points[], new_point)
end
Can someone tell we why ?
The key difference is if there is dependency between observables or not.
In the first example you have time
and then there is ys_1, ys_2
which need to be updated whenever time changes (see reactive programming). In principle you could just define ys_1 = Observable(...)
(same for ys_2
) and then, each time you want to update the plot you write the corresponding data (probably like ys_1.val = <new data>
and ys_2[] = <new data>
such that you only redraw once.)
In the second example there is no dependency, so you don’t to declare any dependencies with @lift
.
1 Like