# Rotating animation of 3D plot changes size as it rotates (GLMakie)

**URL:** <https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219>\
**Category:** General Usage\
**Tags:** makie, glmakie\
**Created:** [October 16, 2025, 11:23pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219 "2025-10-16T23:23:14Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gus\_Hart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gus_hart/32/6987_2.png) [@Gus\_Hart](https://discourse.julialang.org/u/Gus_Hart)\
**Post date:** [October 16, 2025, 11:23pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/1 "2025-10-16T23:23:14Z")

</div>

I’m animating a rotation of a 3D scatter plot. As the figure rotates, it changes size. This is because the camera distance to the plot changes to keep the field of view “full” as the plot rotates but it also avoids cutting off corners. As a result, the plot “pulsates” or “breathes” as it rotates. I’ve used chat to no end to try and fix this but nothing that has been suggested actually solves the problem. It seems the right thing to do would be to fix the distance between the camera and the 3dplot. But every attempt to do that has caused an error or left the problem intact. Anyone have any ideas?

Here is a MWE (not my actual plot).

```julia-auto
using GLMakie

# Create your figure and axis
fig = Figure()
ax = Axis3(fig[1, 1])

# Your plot data here
# Example: surface plot
x = y = range(-5, 5, length=50)
z = [sin(sqrt(x^2 + y^2)) for x in x, y in y]
surface!(ax, x, y, z)

# Set up the camera with fixed axis
cam3d!(ax, fixed_axis=true)

# Now animate the rotation
record(fig, "rotation.mp4", 1:120) do frame
    rotate_cam!(ax.scene, (0, 0.05, 0)) # Rotate around z-axis
end

```

---

<div class="post-metadata">

**Author:** ![RomeoV](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/romeov/32/37687_2.png) [@RomeoV](https://discourse.julialang.org/u/RomeoV)\
**Post date:** [October 17, 2025, 7:13am UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/2 "2025-10-17T07:13:31Z")

</div>

Unfortunately I don’t have a solution. However, for Makie I find you’ll get help much quicker by posting on the makie channel of the Julia Slack.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 17, 2025, 9:12am UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/3 "2025-10-17T09:12:39Z")

</div>

You can try to replace `Axis3` by `LScene`. These two co-exist and behave differently.

I wish `LScene` had all the nice axis features (e.g., labels) of `Axis3` though.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [October 17, 2025, 9:31am UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/4 "2025-10-17T09:31:39Z")

</div>

This is controlled by the `viewmode` setting, you need `:fit` [Axis3 | Makie](https://docs.makie.org/stable/reference/blocks/axis3#viewmode)

I emphasized the problem you mention in the docs snippet below

> viewmode
> 
> Defaults to `:fitzoom`
> 
> The view mode affects the final projection of the axis by fitting the axis cuboid into the available space in different ways.
> 
> - `:fit` uses a fixed scaling such that a tight sphere around the cuboid touches the frame edge. This means that the scaling doesn’t change when rotating the axis (the apparent size of the axis stays the same), but not all available space is used. The chosen `aspect` is maintained using this setting.
> - `:fitzoom` uses a variable scaling such that the closest cuboid corner touches the frame edge. **When rotating the axis, the apparent size of the axis changes which can result in a “pumping” visual effect.** The chosen `aspect` is also maintained using this setting.
> - `:stretch` pulls the cuboid corners to the frame edges such that the available space is filled completely. The chosen `aspect` is not maintained using this setting, so `:stretch` should not be used if a particular aspect is needed.
> - `:free` behaves like `:fit` but changes some interactions. Zooming affects the whole axis rather than just the content. This allows you to zoom in on content without it getting clipped by the 3D bounding box of the Axis3. `zoommode = :cursor` is disabled. Translations can no also affect the axis as a whole with `control + right drag`.

Also, you should not use the `cam_` functions with Axis3, it’s not a plain `Scene` and controls its camera through different attributes. `elevation` and `azimuth` control the two camera rotations

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 17, 2025, 10:15am UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/5 "2025-10-17T10:15:10Z")

</div>

That is very good to know! I don’t remember seeing these options.

Is there any updated guide on choosing between `LScene` and `Axis3`? Should I assume that `Axis3` is always preferred for simple visualization of 3D objects in a coordinate system?

Will experiment with the options above, and possibly replace `LScene` by `Axis3` in our stack.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 17, 2025, 10:18am UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/6 "2025-10-17T10:18:01Z")

</div>

More specifically, how would you choose `Axis3` and fix the option `viewmode = :fit` in Makie.jl recipes like the following:

> <https://github.com/JuliaGeometry/Meshes.jl/blob/4db634951b3da1a3894507fd72f75750f1c37a64/ext/MeshesMakieExt.jl#L40-L43>

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [October 17, 2025, 11:52am UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/7 "2025-10-17T11:52:22Z")

</div>

Axis3 is doing a lot more work for each interaction, which is usually not a problem, but e.g. for WGLMakie it can be quite a bit slower (e.g. all ticks get updated for a simple move of the camera).  
Also, WGLMakie has a javascript fallback for the camera for LScene, so you can still move the camera when exporting a plot to static HTML.  
We do want to upgrade LScene to keep the simpler camera, while improving the static axis to be more modern (the LScene axis is probably one of the oldest plot code living unchanged in Makie).

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 17, 2025, 1:28pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/8 "2025-10-17T13:28:10Z")

</div>

Thank you @sdanisch , so the recommendation at the moment is to continue using `LScene` while it gets improved/refactored. Is that right?

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [October 17, 2025, 1:49pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/9 "2025-10-17T13:49:53Z")

</div>

Depends on your focus 😉  
If you dont care about WGLMakie as much but care about a nice axis, then you should definitely switch to Axis3, or at least make it simple to switch between them.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 17, 2025, 1:59pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/10 "2025-10-17T13:59:23Z")

</div>

I would like to give it a try with `Axis3`, but don’t know how to fix the `viewmode` option in the recipe. Can I just return a lambda function in `Make.args_preferred_axis` to set the axis with pre-fixed options?

```julia
Makie.args_preferred_axis(obj::MyType) = _ -> Makie.Axis3(_, viewmode = :fit)

```

---

<div class="post-metadata">

**Author:** ![Gus\_Hart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gus_hart/32/6987_2.png) [@Gus\_Hart](https://discourse.julialang.org/u/Gus_Hart)\
**Post date:** [October 17, 2025, 2:36pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/11 "2025-10-17T14:36:13Z")

</div>

Fabulous! That did the trick. I appreciate the advice on not using `cam_` functions too. I feel like the Cursor AI also suggested `viewmode=:fit` but it didn’t work for some reason. Maybe because I was still using `cam_`? In any case, this does just what I wanted. Thanks!

```julia-auto
using GLMakie

# Create your figure and axis
fig = Figure()
ax = Axis3(fig[1, 1],viewmode=:fit) # <--- This was the key change

# Your plot data here
# Example: surface plot
x = y = range(-5, 5, length=50)
z = [sin(sqrt(x^2 + y^2)) for x in x, y in y]
surface!(ax, x, y, z)

# Animate using elevation and azimuth
record(fig, "rotation.mp4", 1:120) do frame
    # Rotate around z-axis by changing azimuth
    ax.azimuth = 2π * frame / 120 # Full rotation over 120 frames
    # Keep elevation constant or vary it slightly
    ax.elevation = 15.0 # Fixed elevation angle
end

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [October 17, 2025, 2:43pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/12 "2025-10-17T14:43:06Z")

</div>

But why are the axis panels in front of the plot, they should always switch to the back. Looks like a bug, I don’t see anything obviously wrong in the code

---

<div class="post-metadata">

**Author:** ![Gus\_Hart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gus_hart/32/6987_2.png) [@Gus\_Hart](https://discourse.julialang.org/u/Gus_Hart)\
**Post date:** [October 17, 2025, 3:34pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/13 "2025-10-17T15:34:24Z")

</div>

I didn’t notice that! I have no idea. It doesn’t do that when I interact with the plot directly, only when I make the animation.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [October 17, 2025, 3:48pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/14 "2025-10-17T15:48:01Z")

</div>

Huh, looks like not all observable updates are triggert when only changing ax.azimuth.

---

<div class="post-metadata">

**Author:** ![Gus\_Hart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gus_hart/32/6987_2.png) [@Gus\_Hart](https://discourse.julialang.org/u/Gus_Hart)\
**Post date:** [October 17, 2025, 4:09pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/15 "2025-10-17T16:09:19Z")

</div>

The axis panels are changing and updating during the rotation, but the back seems to be in the front, if you know what I mean…

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [October 21, 2025, 9:05pm UTC](https://discourse.julialang.org/t/rotating-animation-of-3d-plot-changes-size-as-it-rotates-glmakie/133219/16 "2025-10-21T21:05:24Z")

</div>

Alternatively, it could make sense to make `viewmode = :fit` the default in `Axis3`. That way people writing recipes could simply choose between `Axis2` and `Axis3` and get the desired behavior. I believe many people still choose `LScene` because of the “bad” default `viewmode` of `Axis3`.
