将比例系数a_x, a_y 更改为已知的a_x', a_y',条件如下:您希望光标指向相同的坐标(x_c,y_c) 在 R 中.IE.T'(x_c, y_c) = T(x_c, y_c)——相对坐标中的同一个点指向绝对坐标中的同一个位置.我们推导出一个未知偏移量b_x', b_y' 的系统,具有已知的剩余值.它给最后的工作是从widget光标位置找到(x_c, y_c) (x_p, y_p) = T(x_c, y_c):并替换它:用你的话说是mOffset = event->pos() - float(mZoomLevel)/float(oldZoomLevel) *(事件-> pos() - mOffset);I've got a "canvas" that the user can draw pixels, etc. onto. It works well, but my zoom functionality currently uses the same origin regardless of the position of the mouse. I'd like to implement functionality like that of Google Maps' zoom behaviour:That is, the zoom's origin should always be the position of the mouse cursor.What I currently have is not exactly right...My attempts have mostly been stabs in the dark, but I've also tried using the code from this answer without success.main.cpp:#include <QGuiApplication>#include <QtQuick>class Canvas : public QQuickPaintedItem{ Q_OBJECTpublic: Canvas() : mTileWidth(25), mTileHeight(25), mTilesAcross(10), mTilesDown(10), mOffset(QPoint(400, 400)), mZoomLevel(1) { } void paint(QPainter *painter) override { painter->translate(mOffset); const int zoomedTileWidth = mTilesAcross * mZoomLevel; const int zoomedTileHeight = mTilesDown * mZoomLevel; const int zoomedMapWidth = qMin(mTilesAcross * zoomedTileWidth, qFloor(width())); const int zoomedMapHeight = qMin(mTilesDown * zoomedTileHeight, qFloor(height())); painter->fillRect(0, 0, zoomedMapWidth, zoomedMapHeight, QColor(Qt::gray)); for (int y = 0; y < mTilesDown; ++y) { for (int x = 0; x < mTilesAcross; ++x) { const QRect rect(x * zoomedTileWidth, y * zoomedTileHeight, zoomedTileWidth, zoomedTileHeight); painter->drawText(rect, QString::fromLatin1("%1, %2").arg(x).arg(y)); } } }protected: void wheelEvent(QWheelEvent *event) override { const int oldZoomLevel = mZoomLevel; mZoomLevel = qMax(1, qMin(mZoomLevel + (event->angleDelta().y() > 0 ? 1 : -1), 30)); const QPoint cursorPosRelativeToOffset = event->pos() - mOffset; if (mZoomLevel != oldZoomLevel) { mOffset.rx() -= cursorPosRelativeToOffset.x(); mOffset.ry() -= cursorPosRelativeToOffset.y(); // Attempts based on https://stackoverflow.com/a/14085161/904422// mOffset.setX((event->pos().x() * (mZoomLevel - oldZoomLevel)) + (mZoomLevel * -mOffset.x()));// mOffset.setY((event->pos().y() * (mZoomLevel - oldZoomLevel)) + (mZoomLevel * -mOffset.y()));// mOffset.setX((cursorPosRelativeToOffset.x() * (mZoomLevel - oldZoomLevel)) + (mZoomLevel * -mOffset.x()));// mOffset.setY((cursorPosRelativeToOffset.y() * (mZoomLevel - oldZoomLevel)) + (mZoomLevel * -mOffset.y())); update(); } } void keyReleaseEvent(QKeyEvent *event) override { static const int panDistance = 50; switch (event->key()) { case Qt::Key_Left: mOffset.rx() -= panDistance; update(); break; case Qt::Key_Right: mOffset.rx() += panDistance; update(); break; case Qt::Key_Up: mOffset.ry() -= panDistance; update(); break; case Qt::Key_Down: mOffset.ry() += panDistance; update(); break; } }private: const int mTileWidth; const int mTileHeight; const int mTilesAcross; const int mTilesDown; QPoint mOffset; int mZoomLevel;};int main(int argc, char *argv[]){ QGuiApplication app(argc, argv); qmlRegisterType<Canvas>("App", 1, 0, "Canvas"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec();}#include "main.moc"main.qml:import QtQuick 2.5import QtQuick.Window 2.2import App 1.0 as AppWindow { visible: true width: 1200 height: 900 title: qsTr("Hello World") Shortcut { sequence: "Ctrl+Q" onActivated: Qt.quit() } App.Canvas { focus: true anchors.fill: parent }}What am I doing wrong in the wheelEvent() function? 解决方案 You have a rectangle R = [x_0, x_0 + w] x [y_0, y_0 + h] with absolute coordinates. When you map it to a widget (another rectangle), you apply some transformation T to an area W of R. This transformation is linear with offset:Values of a_x, b_x, a_y, b_y are calculated to satisfy some simple conditions, you have already done it.You also have a cursor (x_c, y_c) in R. It's coordinates in W are T(x_c, y_c). Now you want to apply another transformation ,changing scale coefficients a_x, a_y to known a_x', a_y' with following condition: you want your cursor to point at the same coordinates (x_c, y_c) in R. I.e. T'(x_c, y_c) = T(x_c, y_c) — the same point in relative coordinates points to the same position in absolute coordinates. We derive a system for unknown offsets b_x', b_y' with known rest values. It givesLast work is to find (x_c, y_c) from widget cursor position (x_p, y_p) = T(x_c, y_c):and to substitute it:In your terms it ismOffset = event->pos() - float(mZoomLevel) / float(oldZoomLevel) * (event->pos() - mOffset); 这篇关于计算在鼠标光标位置放大的视图偏移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 1403页,肝出来的.. 09-08 10:06