I'm attempting to implement mouse cursor centered zoom in/out on an image. For simplicity, assume I only need to zoom in/out in the horizontal axis. I am using Qt with QPainter to draw my scene and QWidget:: mouseWheelEvent override to calculate a zoom factor and a zoom position.
To put it into words before showing the code, the zoom factor, and zoom position define the transformation needed to transform from the original image into the zoomed image (to put it another way, I don't combine matrices or something similar, but calculate the absolute transformation in the paint event), as can be finally seen here:
void MyWidget::paintEvent(QPaintEvent* e)
{
QPainter painter{this};
painter.translate(m_zoomCenterX, 0.);
painter.scale(m_zoomFactor, 1.);
painter.translate(-m_zoomCenterX, 0.);
// content margins are all 0 btw
painter.drawImage(contentsRect(), m_image);
}
In the mouse wheel event, I try to calculate the scaled difference between the zoom center and the new position which I add to the zoom center. Zoom factor is computed simply by multiplying with a constant according to the angle delta. The final if-else branching does some boundaries checking (which is something I'd like to do so the image stays stretched in the view and doesn't move somewhere I don't want to):
void MyWidget::wheelEvent(QWheelEvent* e)
{
const QRect rect = contentsRect();
// m_zoomCenterX is first initialized to 0 in the MyWidget constructor, m_zoomFactor to 1.
const qreal diff = (e->pos().x() - m_zoomCenterX) / m_zoomFactor;
qDebug() << diff;
m_zoomCenterX += diff;
static constexpr const qreal ZOOM_IN_FACTOR = 1.1,
ZOOM_OUT_FACTOR = .9;
m_zoomFactor *= e->angleDelta().y() > 0. ? ZOOM_IN_FACTOR : ZOOM_OUT_FACTOR;
if (m_zoomFactor < 1.)
{
m_zoomFactor = 1.;
m_zoomCenterX = 0.;
}
else if (m_zoomFactor > 5.)
{
m_zoomFactor = 5.;
}
if (m_zoomCenterX < 0)
{
m_zoomCenter = 0;
}
else if (m_zoomCenterX >= rect.width())
{
m_zoomCenterX = rect.width() - 1;
}
update();
}
This doesn't seem to work once I try to zoom in/out after let's say zooming in (see picture:
, sorry if it's not much), the zoom center position is likely not correctly computed but I'm not sure why. The qDebug line gives me non-zero differences after consecutive scrollings when the cursor is on a new position, but after the first scrolling it should be zero...
I guess it must be something trivial but I'm quite stuck at the moment.