Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-109395

PinchHandler needs to provide translation deltas for non-centered zooming even with weird axis target properties and scaling

    XMLWordPrintable

Details

    Description

      QtLocation provides a challenging case:

           Map {
              id: map
              anchors.fill: parent
              zoomLevel: 14
      
              PinchHandler {
                  id: pinch
      
                  // do not modify x and y properties: use the pan() function
                  xAxis.targetProperty: ""
                  yAxis.targetProperty: ""
                  onTranslationChanged: (delta) => map.pan(-delta.x, -delta.y)
      
                  // convert from multiplicative scale to logarithmic zoomLevel
                  scaleAxis.scaleProvider: (na, delta) => map.zoomLevel + Math.log2(delta)
                  scaleAxis.targetProperty: "zoomLevel" // map is the target already
      
                  // snap to standard north-up orientation if you're close
                  rotationAxis.scaleProvider: (rot, delta) => Math.abs(rot) > 5 ? -rot : 0
                  rotationAxis.targetProperty: "bearing"
              }
      

      QQuickPinchHandler::handlePointerEventImpl emits translationChanged(delta); that needs to be the delta that drives this map.pan() function, at least that's the intention so far.

      When the PinchHandler has a normal item target, and it's just setting scale, rotation, x and y properties, the adjustedPosForTransform() function does a good job generating pos, the position that the target item should have.  So I thought it would work to just subtract the old position from the new one:

              const QVector2D delta(pos.x() - m_xAxis.persistentValue(),
                                    pos.y() - m_yAxis.persistentValue());
              m_xAxis.updateValue(activeTranslation.x(), pos.x(), delta.x());
              m_yAxis.updateValue(activeTranslation.y(), pos.y(), delta.y());
              updateCentroidForTarget();
              emit translationChanged(delta);
      

      But this is not providing enough correction in practice: it still tends to zoom mostly into the center of the map, it's not so easy to zoom into some point in one corner of it.

      We have to be careful not to depend on calling QQmlProperty::read() to get the existing property value in this case (QQuickDragAxis::targetValue() normally does that, but should not in this case, because the property name is empty-string on purpose, to make the property invalid).

      https://doc-snapshots.qt.io/qt6-dev/qml-qtquick-pinchhandler.html#translationChanged-signal

      We might need to clarify docs about what that delta really is.  (But so far hopefully this change will not contradict what they say.)

      Attachments

        Issue Links

          For Gerrit Dashboard: QTBUG-109395
          # Subject Branch Project Status CR V

          Activity

            People

              qt.team.quick.subscriptions Qt Quick and Widgets Team
              srutledg Shawn Rutledge
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes