From b83510f15953e63f42d30832eeb6965bea91c005 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Mon, 27 Mar 2017 15:23:17 +0200 Subject: Improve flicking behavior of QQuickGeoMapGestureArea This patch replaces the two separate flick velocities and displacements for x and y with one vector , so that there will be no discrepancy between the flicking direction and where the map actually flicks Change-Id: I83164107003a423cb7332da5759d83ff689c1b31 Reviewed-by: Alex Blasche --- .../declarativemaps/qquickgeomapgesturearea.cpp | 78 +++++++++------------- 1 file changed, 32 insertions(+), 46 deletions(-) (limited to 'src/location/declarativemaps/qquickgeomapgesturearea.cpp') diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index 39cf8a71..412e33a1 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -60,7 +60,7 @@ #define QML_MAP_FLICK_DEFAULTDECELERATION 2500 #define QML_MAP_FLICK_MAXIMUMDECELERATION 10000 -#define QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD 50 +#define QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD 38 // FlickThreshold determines how far the "mouse" must have moved // before we perform a flick. static const int FlickThreshold = 20; @@ -77,6 +77,11 @@ static const qreal MinimumPinchDelta = 40; // in pixels // Tolerance for starting tilt when sliding vertical static const qreal MinimumPanToTiltDelta = 80; // in pixels; +static qreal distanceBetweenTouchPoints(const QPointF &p1, const QPointF &p2) +{ + return QLineF(p1, p2).length(); +} + // Returns the new map center after anchoring coordinate to anchorPoint on the screen // Approach: find the displacement in (wrapped) mercator space, and apply that to the center static QGeoCoordinate anchorCoordinateToPoint(QGeoMap &map, const QGeoCoordinate &coordinate, const QPointF &anchorPoint) @@ -958,8 +963,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) */ void QQuickGeoMapGestureArea::clearTouchData() { - m_velocityX = 0; - m_velocityY = 0; + m_flickVector = QVector2D(); m_touchPointsCentroid.setX(0); m_touchPointsCentroid.setY(0); m_touchCenterCoord.setLongitude(0); @@ -972,7 +976,7 @@ void QQuickGeoMapGestureArea::clearTouchData() /*! \internal */ -void QQuickGeoMapGestureArea::updateVelocityList(const QPointF &pos) +void QQuickGeoMapGestureArea::updateFlickParameters(const QPointF &pos) { // Take velocity samples every sufficient period of time, used later to determine the flick // duration and speed (when mouse is released). @@ -980,14 +984,12 @@ void QQuickGeoMapGestureArea::updateVelocityList(const QPointF &pos) if (elapsed >= QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { elapsed /= 1000.; - int dyFromLastPos = pos.y() - m_lastPos.y(); - int dxFromLastPos = pos.x() - m_lastPos.x(); + qreal vel = distanceBetweenTouchPoints(pos, m_lastPos) / elapsed; + m_flickVector = (QVector2D(pos) - QVector2D(m_lastPos)).normalized(); + m_flickVector *= qBound(-m_flick.m_maxVelocity, vel, m_flick.m_maxVelocity); + m_lastPos = pos; m_lastPosTime.restart(); - qreal velX = qreal(dxFromLastPos) / elapsed; - qreal velY = qreal(dyFromLastPos) / elapsed; - m_velocityX = qBound(-m_flick.m_maxVelocity, velX, m_flick.m_maxVelocity); - m_velocityY = qBound(-m_flick.m_maxVelocity, velY, m_flick.m_maxVelocity); } } @@ -1139,12 +1141,7 @@ void QQuickGeoMapGestureArea::startOneTouchPoint() void QQuickGeoMapGestureArea::updateOneTouchPoint() { m_touchPointsCentroid = mapFromScene(m_allPoints.at(0).scenePos()); - updateVelocityList(m_touchPointsCentroid); -} - -static qreal distanceBetweenTouchPoints(const QPointF &p1, const QPointF &p2) -{ - return QLineF(p1, p2).length(); + updateFlickParameters(m_touchPointsCentroid); } /*! @@ -1176,7 +1173,7 @@ void QQuickGeoMapGestureArea::updateTwoTouchPoints() QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); m_distanceBetweenTouchPoints = distanceBetweenTouchPoints(p1, p2); m_touchPointsCentroid = (p1 + p2) / 2; - updateVelocityList(m_touchPointsCentroid); + updateFlickParameters(m_touchPointsCentroid); m_twoTouchAngle = touchAngle(p1, p2); } @@ -1714,35 +1711,26 @@ bool QQuickGeoMapGestureArea::tryStartFlick() if ((m_acceptedGestures & FlickGesture) == 0) return false; // if we drag then pause before release we should not cause a flick. - qreal velocityX = 0.0; - qreal velocityY = 0.0; - if (m_lastPosTime.elapsed() < QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) { - velocityY = m_velocityY; - velocityX = m_velocityX; - } - int flickTimeY = 0; - int flickTimeX = 0; - int flickPixelsX = 0; - int flickPixelsY = 0; - if (qAbs(velocityY) > MinimumFlickVelocity && qAbs(m_touchPointsCentroid.y() - m_sceneStartPoint1.y()) > FlickThreshold) { - // calculate Y flick animation values - qreal acceleration = m_flick.m_deceleration; - if ((velocityY > 0.0f) == (m_flick.m_deceleration > 0.0f)) - acceleration = acceleration * -1.0f; - flickTimeY = static_cast(-1000 * velocityY / acceleration); - flickPixelsY = (flickTimeY * velocityY) / (1000.0 * 2); - } - if (qAbs(velocityX) > MinimumFlickVelocity && qAbs(m_touchPointsCentroid.x() - m_sceneStartPoint1.x()) > FlickThreshold) { - // calculate X flick animation values + qreal flickSpeed = 0.0; + if (m_lastPosTime.elapsed() < QML_MAP_FLICK_VELOCITY_SAMPLE_PERIOD) + flickSpeed = m_flickVector.length(); + + int flickTime = 0; + int flickPixels = 0; + QVector2D flickVector; + + if (qAbs(flickSpeed) > MinimumFlickVelocity + && distanceBetweenTouchPoints(m_touchPointsCentroid, m_sceneStartPoint1) > FlickThreshold) { qreal acceleration = m_flick.m_deceleration; - if ((velocityX > 0.0f) == (m_flick.m_deceleration > 0.0f)) + if ((flickSpeed > 0.0f) == (m_flick.m_deceleration > 0.0f)) acceleration = acceleration * -1.0f; - flickTimeX = static_cast(-1000 * velocityX / acceleration); - flickPixelsX = (flickTimeX * velocityX) / (1000.0 * 2); + flickTime = static_cast(-1000 * flickSpeed / acceleration); + flickPixels = (flickTime * flickSpeed) / 2000.0; + flickVector = m_flickVector.normalized() * flickPixels; } - int flickTime = qMax(flickTimeY, flickTimeX); + if (flickTime > 0) { - startFlick(flickPixelsX, flickPixelsY, flickTime); + startFlick(flickVector.x(), flickVector.y(), flickTime); return true; } return false; @@ -1793,8 +1781,7 @@ void QQuickGeoMapGestureArea::stopPan() if (m_flickState == flickActive) { stopFlick(); } else if (m_flickState == panActive) { - m_velocityX = 0; - m_velocityY = 0; + m_flickVector = QVector2D(); setFlickState(flickInactive); m_declarativeMap->setKeepMouseGrab(m_preventStealing); emit panFinished(); @@ -1810,8 +1797,7 @@ void QQuickGeoMapGestureArea::stopFlick() { if (!m_flick.m_animation) return; - m_velocityX = 0; - m_velocityY = 0; + m_flickVector = QVector2D(); if (m_flick.m_animation->isRunning()) m_flick.m_animation->stop(); else -- cgit v1.2.3