← ziglang.inraylib-zigGitHub

2d camera mouse zoom

★★☆☆by Jeffery Myers (@JeffM2501)

There is no browser build of this example yet.

Is it the same as C?

//! raylib [core] example - 2d camera mouse zoom
//!
//! Zig-API translation of examples/core/core_2d_camera_mouse_zoom.c (raylib 6.2).
//! Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5)
//! Example licensed under an unmodified zlib/libpng license.
//! Copyright (c) 2022-2025 Jeffery Myers (@JeffM2501)

const rl = @import("raylib");

const ZoomMode = enum { mouse_wheel, mouse_move };

pub fn main() void {
    // Initialization
    const screen_width = 800;
    const screen_height = 450;

    rl.initWindow(screen_width, screen_height, "raylib [core] example - 2d camera mouse zoom");
    defer rl.closeWindow(); // Close window and OpenGL context

    var camera: rl.Camera2D = .{ .offset = .{ .x = 0, .y = 0 }, .target = .{ .x = 0, .y = 0 }, .rotation = 0, .zoom = 1.0 };

    var zoom_mode: ZoomMode = .mouse_wheel;

    rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second

    // Main game loop
    while (!rl.windowShouldClose()) { // Detect window close button or ESC key
        // Update
        if (rl.isKeyPressed(.one)) {
            zoom_mode = .mouse_wheel;
        } else if (rl.isKeyPressed(.two)) {
            zoom_mode = .mouse_move;
        }

        // Translate based on mouse right click
        if (rl.isMouseButtonDown(.left)) {
            const delta = rl.math.vector2Scale(rl.getMouseDelta(), -1.0 / camera.zoom);
            camera.target = rl.math.vector2Add(camera.target, delta);
        }

        switch (zoom_mode) {
            .mouse_wheel => {
                // Zoom based on mouse wheel
                const wheel = rl.getMouseWheelMove();
                if (wheel != 0) {
                    focusCameraOnMouse(&camera);

                    // Zoom increment
                    // Uses log scaling to provide consistent zoom speed
                    zoomCamera(&camera, 0.2 * wheel);
                }
            },
            .mouse_move => {
                // Zoom based on mouse right click
                if (rl.isMouseButtonPressed(.right)) focusCameraOnMouse(&camera);

                if (rl.isMouseButtonDown(.right)) {
                    // Zoom increment
                    // Uses log scaling to provide consistent zoom speed
                    zoomCamera(&camera, 0.005 * rl.getMouseDelta().x);
                }
            },
        }

        // Draw
        rl.beginDrawing();
        defer rl.endDrawing();

        rl.clearBackground(.ray_white);

        {
            rl.beginMode2D(camera);
            defer rl.endMode2D();

            // Draw the 3d grid, rotated 90 degrees and centered around 0,0
            // just so we have something in the XY plane
            rl.gl.pushMatrix();
            rl.gl.translatef(0, 25 * 50, 0);
            rl.gl.rotatef(90, 1, 0, 0);
            rl.drawGrid(100, 50);
            rl.gl.popMatrix();

            // Draw a reference circle
            rl.drawCircle(@divTrunc(rl.getScreenWidth(), 2), @divTrunc(rl.getScreenHeight(), 2), 50, .maroon);
        }

        // Draw mouse reference
        rl.drawCircleV(rl.getMousePosition(), 4, .dark_gray);
        rl.drawTextEx(
            rl.getFontDefault(),
            rl.textFormat("[{d}, {d}]", .{ rl.getMouseX(), rl.getMouseY() }),
            rl.math.vector2Add(rl.getMousePosition(), .{ .x = -44, .y = -24 }),
            20,
            2,
            .black,
        );

        rl.drawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, .dark_gray);
        switch (zoom_mode) {
            .mouse_wheel => rl.drawText("Mouse left button drag to move, mouse wheel to zoom", 20, 50, 20, .dark_gray),
            .mouse_move => rl.drawText("Mouse left button drag to move, mouse press and move to zoom", 20, 50, 20, .dark_gray),
        }
    }
}

/// Re-anchor the camera so the world point under the cursor stays put while zooming.
fn focusCameraOnMouse(camera: *rl.Camera2D) void {
    // Get the world point that is under the mouse
    const mouse_world_pos = rl.getScreenToWorld2D(rl.getMousePosition(), camera.*);

    // Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
    camera.offset = rl.math.vector2Multiply(rl.getMousePosition(), rl.getWindowScaleDPI());

    // Set the target to match, so that the camera maps the world space point
    // under the cursor to the screen space point under the cursor at any zoom
    camera.target = mouse_world_pos;
}

fn zoomCamera(camera: *rl.Camera2D, scale: f32) void {
    camera.zoom = rl.math.clamp(@exp(@log(camera.zoom) + scale), 0.125, 64.0);
}
/*******************************************************************************************
*
*   raylib [core] example - 2d camera mouse zoom
*
*   Example complexity rating: [★★☆☆] 2/4
*
*   Example originally created with raylib 4.2, last time updated with raylib 4.2
*
*   Example contributed by Jeffery Myers (@JeffM2501) and reviewed by Ramon Santamaria (@raysan5)
*
*   Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
*   BSD-like license that allows static linking with closed source software
*
*   Copyright (c) 2022-2025 Jeffery Myers (@JeffM2501)
*
********************************************************************************************/

#include "raylib.h"

#include "rlgl.h"
#include "raymath.h"

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
    // Initialization
    //--------------------------------------------------------------------------------------
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera mouse zoom");

    Camera2D camera = { 0 };
    camera.zoom = 1.0f;

    int zoomMode = 0;       // 0-Mouse Wheel, 1-Mouse Move

    SetTargetFPS(60);       // Set our game to run at 60 frames-per-second
    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!WindowShouldClose())        // Detect window close button or ESC key
    {
        // Update
        //----------------------------------------------------------------------------------
        if (IsKeyPressed(KEY_ONE)) zoomMode = 0;
        else if (IsKeyPressed(KEY_TWO)) zoomMode = 1;

        // Translate based on mouse right click
        if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
        {
            Vector2 delta = GetMouseDelta();
            delta = Vector2Scale(delta, -1.0f/camera.zoom);
            camera.target = Vector2Add(camera.target, delta);
        }

        if (zoomMode == 0)
        {
            // Zoom based on mouse wheel
            float wheel = GetMouseWheelMove();
            if (wheel != 0)
            {
                // Get the world point that is under the mouse
                Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);

                // Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
                camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());

                // Set the target to match, so that the camera maps the world space point
                // under the cursor to the screen space point under the cursor at any zoom
                camera.target = mouseWorldPos;

                // Zoom increment
                // Uses log scaling to provide consistent zoom speed
                float scale = 0.2f*wheel;
                camera.zoom = Clamp(expf(logf(camera.zoom)+scale), 0.125f, 64.0f);
            }
        }
        else
        {
            // Zoom based on mouse right click
            if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
            {
                // Get the world point that is under the mouse
                Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);

                // Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
                camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());

                // Set the target to match, so that the camera maps the world space point
                // under the cursor to the screen space point under the cursor at any zoom
                camera.target = mouseWorldPos;
            }

            if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
            {
                // Zoom increment
                // Uses log scaling to provide consistent zoom speed
                float deltaX = GetMouseDelta().x;
                float scale = 0.005f*deltaX;
                camera.zoom = Clamp(expf(logf(camera.zoom)+scale), 0.125f, 64.0f);
            }
        }
        //----------------------------------------------------------------------------------

        // Draw
        //----------------------------------------------------------------------------------
        BeginDrawing();
            ClearBackground(RAYWHITE);

            BeginMode2D(camera);
                // Draw the 3d grid, rotated 90 degrees and centered around 0,0
                // just so we have something in the XY plane
                rlPushMatrix();
                    rlTranslatef(0, 25*50, 0);
                    rlRotatef(90, 1, 0, 0);
                    DrawGrid(100, 50);
                rlPopMatrix();

                // Draw a reference circle
                DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON);
            EndMode2D();

            // Draw mouse reference
            //Vector2 mousePos = GetWorldToScreen2D(GetMousePosition(), camera)
            DrawCircleV(GetMousePosition(), 4, DARKGRAY);
            DrawTextEx(GetFontDefault(), TextFormat("[%i, %i]", GetMouseX(), GetMouseY()),
                Vector2Add(GetMousePosition(), (Vector2){ -44, -24 }), 20, 2, BLACK);

            DrawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, DARKGRAY);
            if (zoomMode == 0) DrawText("Mouse left button drag to move, mouse wheel to zoom", 20, 50, 20, DARKGRAY);
            else DrawText("Mouse left button drag to move, mouse press and move to zoom", 20, 50, 20, DARKGRAY);

        EndDrawing();
        //----------------------------------------------------------------------------------
    }

    // De-Initialization
    //--------------------------------------------------------------------------------------
    CloseWindow();        // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

From raylib 6.2. The original on GitHub.