Skip to content

[ENH]: Add ability to snap view to primary axis planes in 3D plots #23544

Open

Description

@scottshambaugh

Problem

In matlab, you can right-click on a 3D plot and a context menu pops up that gives you the option to 'Go to X-Y view', 'Go to X-Z view', and 'Go to Y-Z view'. The view then snaps to viewing that plane face-on. Something similar would be very useful in matplotlib.

image

Proposed solution

Either a right-click menu or a toolbar dropdown with similar snapping options. That would then set the appropriate ax.view_init(elev, azim, roll) elevation and azimuth view angles.

Activity

  1. scottshambaugh commented on Aug 3, 2022

    @scottshambaugh
    ContributorAuthor

    Here are the view angles I would propose. This matches matlab's conventions and keeps the roll angle at 0. The inverse views show the other 3 sides of the box, and are defined by a 180 deg rotation about the local vertical axis. Might be worth a PR at some point to make all the axes in these orientations show along the bottom and left edges. (Edit: see #23644)

    image

    import matplotlib.pyplot as plt
    
    # (view, (elev, azim, roll))
    views = [( 'XY', (90, -90, 0)), 
             ( 'XZ', (0, -90, 0)),  
             ( 'YZ', (0, 0, 0)), 
             ('-XY', (-90, 90, 0)), 
             ('-XZ', (0, 90, 0)),
             ('-YZ', (0, 180, 0)), 
            ]
    
    fig, axs = plt.subplots(2, 3, subplot_kw={'projection': '3d'})
    for i, ax in enumerate([ax for ax_row in axs for ax in ax_row]):
        ax.set_xlabel('x')
        ax.set_ylabel('y')
        ax.set_zlabel('z')
        ax.set_title(views[i][0])
        ax.set_proj_type('ortho')
        ax.view_init(elev=views[i][1][0], azim=views[i][1][1], roll=views[i][1][2])
  2. oscargus commented on Aug 10, 2022

    @oscargus
    Member

    This requires adding a right-click menu in a backend independent way? I think that will be a huge benefit in general as well, being a right-click person...

  3. scottshambaugh commented on Aug 10, 2022

    @scottshambaugh
    ContributorAuthor

    Yeah, I see the scope of this as twofold.

    1. Programmatic interface to look at primary view planes. I think DOC: view_init docstring for 3d axes primary view angles #23600 is good enough to suffice this, but maybe we accept "XY", etc. strings as an input to view_init as well.

    2. Right-click context menu to expose this to the gui. That's a pretty big chunk of work I'd expect.

  4. github-actions commented on Dec 19, 2025

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  5. timhoffm commented on Dec 19, 2025

    @timhoffm
    Member

    Maybe a simpler feature would be to snap the angles to discrete steps (say, 5 or 10 degrees) if a modifier key is pressed.

  6. WeatherGod commented on Dec 19, 2025

    @WeatherGod
    Member
  7. QuLogic commented on Dec 23, 2025

    @QuLogic
    Member

    I vaguely recall a question somewhere about trying to produce an XYZ "cursor" that has arrows in the 3 primary directions and rotates to match the 3D Axes by making an inset 3D Axes and trying to lock the view direction to the main one somehow, but I cannot remember where I saw it.

    I wonder if we would want to implement one of those, for which snapping to a primary plane would mean clicking on one of the XYZ arrows. This would be something like the orbit navigation gizmo in Blender: https://docs.blender.org/manual/en/latest/editors/3dview/navigate/introduction.html#navigation-gizmo

  8. AdwaithBatchu commented on Dec 23, 2025

    @AdwaithBatchu

    Hi everyone, I am interested in working on this.

    Reading through the discussion, I see there are a few proposed ways to handle view snapping (modifier keys, programmatic interface, context menus, XYZ "cursor"). I am posting this comment to clarify what would be the preferred approach.

    I am currently working on the Right-Click Context Menu approach. I have a working prototype for the Qt and WebAgg backends that allows users to right-click a 3D plot and snap to primary views. I plan to focus my initial PR on this context menu interaction to establish the UI pattern. However, if the maintainers prefer modifier key or a programmatic interface as the priority, I am happy to pivot or include those in a follow-up.

  9. timhoffm commented on Dec 23, 2025

    @timhoffm
    Member

    A right-click context menu would generally be nice to have (also outside the scoreboard this issue. However, doing this properly is a hard task. From your limited public GitHub profile, I‘d infer that this is probably too hard for you. But please judge yourself.

    Some aspects to consider:

    • The context menu must be context-specific; I.e. depend on what’s under the cursor. Note that a figure may contain multiple independent 3D Axes.
    • The context menu must be implementable in all backends. Though we may not need implementations in all backends right now, the solution must fit to our event and backend architecture, and you must make sure that there are no fundamental blockers for implementing in all backends.

    If you have experience with this and the mentioned aspects instill a clear solution strategy with you, this is probably a good fit, if not, I‘d have doubts that you can come up with a suitable solution.

  10. scottshambaugh commented on Jan 16, 2026

    @scottshambaugh
    ContributorAuthor

    Noting for later, some or all of the below buttons may be useful for setting the view as well. At the risk of clutter, this would complete the set of every head-on orientation:

    • Go to -X-Y view
    • Go to -Y-Z view
    • Go to -X-Z view
    • Rotate view ↻ Clockwise
    • Rotate view ↺ Counter-Clockwise
  11. scottshambaugh commented on Jan 22, 2026

    @scottshambaugh
    ContributorAuthor

    We talked about this in the weekly meeting today, and have a consensus that it's better to build a menu / hamburger drop-down into the toolbar rather a right-click context menu. Reasoning:

    • There are others using context menus out there and we would need to define an API that they could adhere to (a decent amount of effort)
    • We own the figure GUI, so no concerns about API compatibility there
    • A toolbar addition is more discoverable than a context menu, and is more accessible since it doesn't require a different right-click or long-press modality to access
  12. AdwaithBatchu commented on Feb 3, 2026

    @AdwaithBatchu

    @scottshambaugh I would like to know your thoughts on how to handle cases with multiple 3D axes.

    Few ideas that hit my mind are:

    1. Create a nested menu, one for each axes. Like in the image below
    Image

    But one problem with this approach is that, It isn't clear how to name the menu items. As in, it may not always be obvious which axes "Axes 1" refers to.

    1. Change view of most recently clicked-on subplot.
  13. scottshambaugh commented on Feb 3, 2026

    @scottshambaugh
    ContributorAuthor

    That's a really good point that we didn't discuss... let me bring it up in the weekly meeting again on Thursday. You're welcome to join as well if you'd like, the zoom link is at the link above.

  14. scottshambaugh commented on Feb 5, 2026

    @scottshambaugh
    ContributorAuthor

    Hey @AdwaithBatchu, we talked for a while today about different options to solve this for subplots, and think the context menu is actually probably the best path forward! Your work so far was very helpful in showing a proof of concept for that discussion. I'll reopen and add a note or two to the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions