diff options
author | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2017-09-28 13:39:28 +0300 |
---|---|---|
committer | Arsentiy Milchakov <milcars@mapswithme.com> | 2017-09-29 11:53:54 +0300 |
commit | cccd8608896f1c95758aaae3f33badaca5772ae1 (patch) | |
tree | b48dc752d1cfebd71751155a9c151237dcdf0364 | |
parent | 46deebc993555d639dbfa412df89d3084959b319 (diff) |
Improved kinetic scroll
-rw-r--r-- | drape_frontend/kinetic_scroller.cpp | 32 | ||||
-rw-r--r-- | drape_frontend/kinetic_scroller.hpp | 6 | ||||
-rw-r--r-- | drape_frontend/user_event_stream.cpp | 3 |
3 files changed, 37 insertions, 4 deletions
diff --git a/drape_frontend/kinetic_scroller.cpp b/drape_frontend/kinetic_scroller.cpp index c4c67bda76..cb46a97283 100644 --- a/drape_frontend/kinetic_scroller.cpp +++ b/drape_frontend/kinetic_scroller.cpp @@ -15,6 +15,7 @@ double const kKineticThreshold = 50.0; double const kKineticAcceleration = 0.4; double const kKineticMaxSpeedStart = 1000.0; // pixels per second double const kKineticMaxSpeedEnd = 10000.0; // pixels per second +double const kInstantVelocityThresholdUnscaled = 200.0; // pixels per second double CalculateKineticMaxSpeed(ScreenBase const & modelView) { @@ -117,12 +118,29 @@ private: TObjectProperties m_properties; }; -void KineticScroller::Init(ScreenBase const &modelView) +void KineticScroller::Init(ScreenBase const & modelView) { ASSERT(!m_isActive, ()); m_isActive = true; m_lastRect = modelView.GlobalRect(); m_lastTimestamp = std::chrono::steady_clock::now(); + m_updatePosition = modelView.GlobalRect().GlobalCenter(); + m_updateTimestamp = m_lastTimestamp; +} + +void KineticScroller::Update(ScreenBase const & modelView) +{ + ASSERT(m_isActive, ()); + using namespace std::chrono; + auto const nowTimestamp = std::chrono::steady_clock::now(); + auto const curPos = modelView.GlobalRect().GlobalCenter(); + + double const instantPixelLen = (modelView.GtoP(curPos) - modelView.GtoP(m_updatePosition)).Length(); + auto const updateElapsed = duration_cast<duration<double>>(nowTimestamp - m_updateTimestamp).count(); + m_instantVelocity = (updateElapsed >= 1e-5) ? instantPixelLen / updateElapsed : 0.0; + + m_updateTimestamp = nowTimestamp; + m_updatePosition = curPos; } bool KineticScroller::IsActive() const @@ -139,9 +157,9 @@ m2::PointD KineticScroller::GetDirection(ScreenBase const & modelView) const using namespace std::chrono; auto const nowTimestamp = steady_clock::now(); auto const elapsed = duration_cast<duration<double>>(nowTimestamp - m_lastTimestamp).count(); + m2::PointD const currentCenter = modelView.GlobalRect().GlobalCenter(); m2::PointD const lastCenter = m_lastRect.GlobalCenter(); - m2::PointD const currentCenter = modelView.GlobalRect().GlobalCenter(); double const pxDeltaLength = (modelView.GtoP(currentCenter) - modelView.GtoP(lastCenter)).Length(); m2::PointD delta = currentCenter - lastCenter; if (!delta.IsAlmostZero()) @@ -164,7 +182,15 @@ void KineticScroller::Cancel() drape_ptr<Animation> KineticScroller::CreateKineticAnimation(ScreenBase const & modelView) { - static double kVelocityThreshold = kKineticThreshold * VisualParams::Instance().GetVisualScale(); + static double vs = VisualParams::Instance().GetVisualScale(); + static double kVelocityThreshold = kKineticThreshold * vs; + static double kInstantVelocityThreshold = kInstantVelocityThresholdUnscaled * vs; + + if (m_instantVelocity < kInstantVelocityThreshold) + { + Cancel(); + return drape_ptr<Animation>(); + } auto const direction = GetDirection(modelView); Cancel(); diff --git a/drape_frontend/kinetic_scroller.hpp b/drape_frontend/kinetic_scroller.hpp index d62a101a61..d3950a7870 100644 --- a/drape_frontend/kinetic_scroller.hpp +++ b/drape_frontend/kinetic_scroller.hpp @@ -13,7 +13,8 @@ namespace df class KineticScroller { public: - void Init(ScreenBase const &modelView); + void Init(ScreenBase const & modelView); + void Update(ScreenBase const & modelView); bool IsActive() const; void Cancel(); drape_ptr<Animation> CreateKineticAnimation(ScreenBase const & modelView); @@ -22,7 +23,10 @@ private: m2::PointD GetDirection(ScreenBase const & modelView) const; std::chrono::steady_clock::time_point m_lastTimestamp; + std::chrono::steady_clock::time_point m_updateTimestamp; bool m_isActive = false; m2::AnyRectD m_lastRect; + m2::PointD m_updatePosition; + double m_instantVelocity = 0.0; }; } // namespace df diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 6967917ae3..ac3f176edb 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -987,6 +987,9 @@ void UserEventStream::Drag(Touch const & t) TEST_CALL(DRAG); ASSERT_EQUAL(m_state, STATE_DRAG, ()); m_navigator.DoDrag(t.m_location); + + if (m_kineticScrollEnabled && m_scroller.IsActive()) + m_scroller.Update(m_navigator.Screen()); } bool UserEventStream::EndDrag(Touch const & t, bool cancelled) |