2d camera mouse zoom
There is no browser build of this example yet.
Is it the same as C?
- Desktop:verified The Zig version renders a final frame that is byte-identical to the C example.
- Browser:not checked yet The browser comparison does not cover this example yet.
//! 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.