I've been trying something similar and I'd like to improve @Mario's answer.
In fact, the use of mapPixelToCoords
ends being somehow expensive. This is something weird, because mapPixelToCoords
only applies some matrices operations to the coordinates, but the thing is when I use mapPixelToCoords
, my image shakes like crazy when the zoom wasn't the original one.
In my case, I prefer to keep the accumulated zoom and multiply that deltaPos
by the zoom level.
Changes from @Mario's code
New Variable
accumZoom
:
double accumZoom = 1;
Button Pressed Event:
case sf::Event::MouseButtonPressed:
// Mouse button is pressed, get the position and set moving as active
if (event.mouseButton.button == 0) {
moving = true;
oldPos = sf::Vector2f(sf::Mouse::getPosition(window)); // No call to mapPixelToCoords
}
break;
Mouse Moved Event:
case sf::Event::MouseMoved:
{
// Ignore mouse movement unless a button is pressed (see above)
if (!moving)
break;
// Determine the new position in world coordinates
const sf::Vector2f newPos = sf::Vector2f(event.mouseMove.x, event.mouseMove.y);
// Determine how the cursor has moved
// Swap these to invert the movement direction
const sf::Vector2f deltaPos = oldPos - newPos;
// Applying zoom "reduction" (or "augmentation")
deltaPos.x *= accumZoom;
deltaPos.y *= accumZoom;
// Move our view accordingly and update the window
view.move(deltaPos); // <-- Here I use move
window.setView(view);
// Save the new position as the old one
// We're recalculating this, since we've changed the view
oldPos = newPos; // With move, I don't need to recalculate
break;
}
Mouse Wheel Scrolled Event:
case sf::Event::MouseWheelScrolled:
// Ignore the mouse wheel unless we're not moving
if (moving)
break;
// Determine the scroll direction and adjust the zoom level
// Again, you can swap these to invert the direction
if (event.mouseWheelScroll.delta <= -1)
zoom = std::min(2.f, zoom + .1f);
else if (event.mouseWheelScroll.delta >= 1)
zoom = std::max(.5f, zoom - .1f);
accumZoom *= zoom; // <-- accumulate zoom
// Update our view
view.setSize(window.getDefaultView().getSize()); // Reset the size
view.zoom(zoom); // Apply the zoom level (this transforms the view)
window.setView(view);
break;