Makie - Need Help with Animation

Hello everyone!

I have a function that plots a graph for a given frame (time point):

function create_figure(frame)
    time = (frame-1)*t_step

    xs = range(0, L, length=500)
    ys = range(0, L, length=500)
    zs = [vort(x,y, time) for x in xs, y in ys]
    
    xs2 = LinRange(0, L, 31)
    ys2 = LinRange(0, L, 31)
    us2 = [u(x,y, time) for x in xs2, y in ys2]
    vs2 = [v(x,y, time) for x in xs2, y in ys2]

    tracks_num = 10 # number of visible tracks
    tracks_len = fill(1, tracks_num)

    for i in 1:tracks_num
        tracks_len[i] = Int(min(frame, length(x_tracks_TP[i])))
    end

    fig = Figure(size = (600, 550))

    ax = Axis(fig[1, 1],
        title = "TP: V_a = 0.3 V_m, t="*@sprintf("%.2f", time), titlesize=24,
        xlabel = "x", xlabelsize=20, xticklabelsize=20,
        ylabel = "y", ylabelsize=20, yticklabelsize=20,
        aspect = 1, limits = ((0, L), (0,L))
    )

    hm = heatmap!(ax, x, y, zs, colormap = :viridis, alpha=1.0, colorrange=(-50, 50))
    Colorbar(fig[:, end+1], hm, ticklabelsize=18)

    hlines!(ax, LinRange(0, L, N_tile+1), color=:white, alpha=0.5)
    vlines!(ax, LinRange(0, L, N_tile+1), color=:white, alpha=0.5)

    arrows!(ax, xs2, ys2, us2, vs2, arrowsize = 6, lengthscale = 0.02,)

    for i in 1:tracks_num
        lines!(ax, x_tracks_TP[i][1:tracks_len[i]], y_tracks_TP[i][1:tracks_len[i]], color=:white)
    end

    poly!(ax, Circle(Point2f(xA, yA), rA), color = :tomato)
    text!(xA, yA, text = "A", align = (:center, :center))

    poly!(ax, Circle(Point2f(xB, yB), rB), color = :tomato)
    text!(xB, yB, text = "B", align = (:center, :center))

    return fig
end   

Now I want to go through the frame numbers in a loop and make a video sequence. I have tried

frame = Observable(1)
fig = @lift(create_figure($frame))

frame_range = 1:100

record(fig, "video.mp4", frame_range; framerate = 30) do i
    frame[] = i
end

but this leads to an error

MethodError: no method matching record(::var"#341#342", ::Observable{Figure}, ::String, ::UnitRange{Int64}; framerate::Int64)
The function `record` exists, but no method is defined for this combination of argument types.

If I change fig to fig[] in the record then the frames don’t change and I get a video that always shows the first frame. What is the easiest way to create a video sequence having a function that builds a picture at a given moment in time?

In the end, I found a solution that suits me:

using CairoMakie, Printf

frame = Observable(1)
time = @lift(($frame-1)*Δt)

xs = range(0, L, length=500)
ys = range(0, L, length=500)
zs = @lift([vort(x,y, $time) for x in xs, y in ys])
    
xs2 = LinRange(0, L, 31)
ys2 = LinRange(0, L, 31)
us2 = @lift([u(x,y, $time) for x in xs2, y in ys2])
vs2 = @lift([v(x,y, $time) for x in xs2, y in ys2])

points_list = Any[]

for p in 1:30
    points = Observable(Point2f[(xA, yA)])
    push!(points_list, points)
end

fig = Figure(size = (600, 550))

ax = Axis(fig[1, 1],
    title = @lift("TP: V=0.3, t="*@sprintf("%.2f", $time)), titlesize=24,
    xlabel = "x", xlabelsize=20, xticklabelsize=20,
    ylabel = "y", ylabelsize=20, yticklabelsize=20,
    aspect = 1, limits = ((0, L), (0,L))
)

hm = heatmap!(ax, x, y, zs, colormap = :viridis, alpha=1.0, colorrange=(-50, 50))
Colorbar(fig[:, end+1], hm, ticklabelsize=18)

hlines!(ax, LinRange(0, L, N_tile+1), color=:white, alpha=0.5)
vlines!(ax, LinRange(0, L, N_tile+1), color=:white, alpha=0.5)

arrows!(ax, xs2, ys2, us2, vs2, arrowsize = 6, lengthscale = 0.02,)

for p in 1:30
    success_TP[p]==1 ? c=:tomato : c=:white
    lines!(ax, points_list[p], color=c)
end
    
poly!(ax, Circle(Point2f(xA, yA), rA), color = :tomato)
text!(xA, yA, text = "A", align = (:center, :center))

poly!(ax, Circle(Point2f(xB, yB), rB), color = :tomato)
text!(xB, yB, text = "B", align = (:center, :center))  

frames = 1:500

record(fig, "TP_V=0.3.mp4", frames; framerate = 20) do i
    mod(i, 100) == 0 && @show i
    frame[] = i    
    for (idx, points) in enumerate(points_list)
        if i<=length(x_tracks_TP[idx])
            new_point = Point2f(x_tracks_TP[idx][i], y_tracks_TP[idx][i])
            points[] = push!(points[], new_point)
        end
    end
end