diff options
author | Ralf Engels <ralf.engels@nokia.com> | 2010-04-09 17:30:31 +0200 |
---|---|---|
committer | Ralf Engels <ralf.engels@nokia.com> | 2010-04-09 17:30:31 +0200 |
commit | 88e018356973866017db25cbc16700fd3da59a99 (patch) | |
tree | 62e9b27177848f215bd492fc126537c5c6844c28 | |
parent | f557f9a5099a07dfa599e394c779558a7e1fb167 (diff) |
Fiddling around with the kinetic scroller
-rw-r--r-- | main.cpp | 4 | ||||
-rw-r--r-- | qkineticscroller.cpp | 59 | ||||
-rw-r--r-- | qkineticscroller.h | 2 |
3 files changed, 52 insertions, 13 deletions
@@ -14,5 +14,7 @@ int main(int argc, char **argv) s->setWidget(lw); lw->show(); + s->scrollTo(QPointF(80,800)); + return a.exec(); -}
\ No newline at end of file +} diff --git a/qkineticscroller.cpp b/qkineticscroller.cpp index 04b0b83..2197ec8 100644 --- a/qkineticscroller.cpp +++ b/qkineticscroller.cpp @@ -190,7 +190,7 @@ void QKineticScroller::resetScrollMetrics() metrics.insert(FramesPerSecond, qreal(20)); #else metrics.insert(DragVelocitySmoothingFactor, qreal(0.02)); - metrics.insert(ExponentialDecelerationBase, qreal(0)); + metrics.insert(ExponentialDecelerationBase, qreal(1)); metrics.insert(LinearDecelerationFactor, qreal(0.38)); metrics.insert(OvershootSpringConstant, qreal(15.0)); metrics.insert(OvershootDragResistanceFactor, qreal(0.5)); @@ -712,12 +712,10 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time_ms) if (overshootDistance.x() && ((overshootDistance.x() > 0) != (newOvershootDistance.x() > 0))) { overshootDistance.setX(0); velocity.setX(0); - scrollToX = false; } if (overshootDistance.y() && ((overshootDistance.y() > 0) != (newOvershootDistance.y() > 0))) { overshootDistance.setY(0); velocity.setY(0); - scrollToY = false; } } @@ -739,11 +737,14 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time_ms) velocity.setX(qBound(-overshootMaximumVelocity, velocity.x(), overshootMaximumVelocity)); } else if (scrollToX) { - if (qAbs(velocity.x()) >= qreal(3.0 / 1000 /* 3mm/s */)) + if (qAbs(velocity.x()) * exponentialDecelerationPerFrame > linearDecelerationPerFrame + qreal(30.0 / 1000) )/* 30 px/s */ velocity.setX(decelerate(velocity.x(), exponentialDecelerationPerFrame, linearDecelerationPerFrame)); + else + velocity.setX((velocity.x()<0 ? -1.0 : 1.0) * qreal(30.0 / 1000)); // - target reached? qreal dist = scrollToPosition.x() - q->contentPosition().x(); +qDebug() << "scroll to x" << scrollToPosition.x() << "v:"<< velocity.x() << " dist " << dist; if ((velocity.x() > 0.0 && dist <= 0.0) || (velocity.x() < 0.0 && dist >= 0.0)) { velocity.setX(0.0); scrollToX = false; @@ -759,11 +760,14 @@ void QKineticScrollerPrivate::timerEventWhileScrolling(qint64 time_ms) velocity.setY(qBound(-overshootMaximumVelocity, velocity.y(), overshootMaximumVelocity)); } else if (scrollToY) { - if (qAbs(velocity.y()) >= qreal(3.0 / 1000 /* 3mm/s */)) + if (qAbs(velocity.y()) * exponentialDecelerationPerFrame > linearDecelerationPerFrame + qreal(30.0 / 1000) )/* 30 px/s */ velocity.setY(decelerate(velocity.y(), exponentialDecelerationPerFrame, linearDecelerationPerFrame)); + else + velocity.setY((velocity.y()<0 ? -1.0 : 1.0) * qreal(30.0 / 1000)); // - target reached? qreal dist = scrollToPosition.y() - q->contentPosition().y(); +qDebug() << "scroll to y" << scrollToPosition.y() << "v:"<< velocity.y() << " dist " << dist; if ((velocity.y() > 0.0 && dist <= 0.0) || (velocity.y() < 0.0 && dist >= 0.0)) { velocity.setY(0.0); scrollToY = false; @@ -821,6 +825,8 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) killTimer(timerId); timerId = 0; } + scrollToX = false; + scrollToY = false; velocity = QPointF(0, 0); break; @@ -837,11 +843,11 @@ void QKineticScrollerPrivate::setState(QKineticScroller::State newstate) break; case QKineticScroller::StateScrolling: - if (state == QKineticScroller::StatePressed) { + // if (state == QKineticScroller::StatePressed) { if (!timerId) { timerId = startTimer(1000 / framesPerSecond); } - } + // } scrollTimer.start(); break; } @@ -867,20 +873,45 @@ void QKineticScroller::scrollTo(const QPointF &pos, int scrollTime) { Q_D(QKineticScroller); - if ((pos == contentPosition()) || (d->state != QKineticScroller::StateInactive)) { + qreal time = qreal(scrollTime) / 1000; + + if ((pos == contentPosition()) || + (d->state == QKineticScroller::StatePressed) || + (d->state == QKineticScroller::StateDragging)) { return; } - // v(t) = vstart * exponentialDecelerationBase ^ t + linearDecelerationFactor * t + // estimate the minimal start velocity + // if the start velocity is below that then the scrolling would stop before scrollTime. + qreal vMin = d->linearDecelerationFactor * time / qPow(d->exponentialDecelerationBase, time); + + // estimate of the distance passed within the vMin time during scrollTime + qreal distMin = qreal(scrollTime) * vMin / 2.0; + + qKSDebug() << "QAbstractKineticScroller::scrollTo v, dis(" << vMin << ", " << distMin; + + QPointF v = QPointF((pos.x()-contentPosition().x()) / distMin * vMin, + (pos.y()-contentPosition().y()) / distMin * vMin); + + qKSDebug() << "QAbstractKineticScroller::scrollTo(" << pos << ", " << v; + + // v(t) = vstart * exponentialDecelerationBase ^ t - linearDecelerationFactor * t // pos(t) = integrate(v(t) * dt) - // pos(t) = vstart * eDB ^ t / ln(eDB) + lDF / 2 * t ^ 2 + // pos(t) = vstart * eDB ^ t / ln(eDB) - lDF / (2 * t ^ 2) // // pos(scrollTime) = pos - contentsPos() // vstart = (lDF / 2 * scrollTime ^ 2 - (pos - contentPos())) * ln(eDB) / eDB ^ scrollTime +/* - QPointF v = QPointF(1, 1) * d->linearDecelerationFactor / 2 * scrollTime * scrollTime - (pos - contentPosition()) * + QPointF v = QPointF(-1, -1) * d->linearDecelerationFactor / (qreal(2) * qreal(scrollTime) * qreal(scrollTime)) - (pos - contentPosition()) * qLn(d->exponentialDecelerationBase) / qPow(d->exponentialDecelerationBase, scrollTime); + qKSDebug() << "QAbstractKineticScroller::scrollTo(" << pos << ", " << v; + qKSDebug() << "QAbstr " << d->linearDecelerationFactor <<" 1: "<< (qreal(2) * qreal(scrollTime) * qreal(scrollTime)) << " 2: " << (pos - contentPosition()) << " 3: " << + qLn(d->exponentialDecelerationBase) << "4: " << qPow(d->exponentialDecelerationBase, scrollTime); + + v = QPointF(0.01, 0.01); +*/ // start the scrolling d->scrollToPosition = pos; d->scrollToX = true; @@ -941,6 +972,12 @@ void QKineticScrollerPrivate::setContentPositionHelper(const QPointF &pos) clampedPos.setX(qBound(qreal(0), pos.x(), maxPos.x())); clampedPos.setY(qBound(qreal(0), pos.y(), maxPos.y())); + // -- stop scroll to if hitting boundary + if (clampedPos.x() != pos.x()) + scrollToX = false; + if (clampedPos.y() != pos.y()) + scrollToY = false; + bool alwaysOvershoot = (overshootPolicy == QKineticScroller::OvershootAlwaysOn); qreal overshootX = (maxPos.x() || alwaysOvershoot) ? pos.x() - clampedPos.x() : 0; qreal overshootY = (maxPos.y() || alwaysOvershoot) ? pos.y() - clampedPos.y() : 0; diff --git a/qkineticscroller.h b/qkineticscroller.h index 3b31b88..a574891 100644 --- a/qkineticscroller.h +++ b/qkineticscroller.h @@ -88,7 +88,7 @@ public: { DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF) - LinearDecelerationFactor, // qreal [0..1] + LinearDecelerationFactor, // qreal [m/s^2] ExponentialDecelerationBase, // qreal [0..1] OvershootSpringConstant, // qreal [0..1] OvershootDragResistanceFactor, // qreal [0..1] |