forked from organicmaps/organicmaps
[core] zoom-in\zoom-out animation
This commit is contained in:
parent
979f82bf09
commit
495712584b
3 changed files with 119 additions and 34 deletions
|
@ -1005,7 +1005,7 @@ void Framework::ScaleToPoint(ScaleToPointEvent const & e)
|
|||
m2::PointD const pt = (locationState->GetLocationProcessMode() == location::ELocationDoNothing) ?
|
||||
m_navigator.ShiftPoint(e.Pt()) : GetPixelCenter();
|
||||
|
||||
m_navigator.ScaleToPoint(pt, e.ScaleFactor(), ElapsedSeconds());
|
||||
m_animController->AddTask(m_navigator.ScaleToPointAnim(pt, e.ScaleFactor(), 0.5));
|
||||
|
||||
Invalidate();
|
||||
UpdateUserViewportChanged();
|
||||
|
@ -1018,7 +1018,7 @@ void Framework::ScaleDefault(bool enlarge)
|
|||
|
||||
void Framework::Scale(double scale)
|
||||
{
|
||||
m_navigator.Scale(scale);
|
||||
m_animController->AddTask(m_navigator.ScaleAnim(scale));
|
||||
|
||||
Invalidate();
|
||||
UpdateUserViewportChanged();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "../base/std_serialization.hpp"
|
||||
#include "../base/logging.hpp"
|
||||
|
||||
#include "../std/function.hpp"
|
||||
#include "../std/bind.hpp"
|
||||
|
||||
namespace
|
||||
|
@ -402,42 +403,115 @@ void Navigator::StartScale(m2::PointD const & pt1, m2::PointD const & pt2, doubl
|
|||
m_InAction = true;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void CalcScalePoints(m2::PointD const & pt, double factor, m2::RectD const & pxRect,
|
||||
m2::PointD & startPt, m2::PointD & endPt)
|
||||
{
|
||||
// pt is in x0, x0 + width
|
||||
|
||||
if (pt.x != pxRect.maxX())
|
||||
{
|
||||
// start scaling point is 1 / factor way between pt and right border
|
||||
startPt.x = pt.x + ((pxRect.maxX() - pt.x) / factor);
|
||||
endPt.x = pxRect.maxX();
|
||||
}
|
||||
else
|
||||
{
|
||||
// start scaling point is 1 - 1/factor way between left border and pt
|
||||
startPt.x = pt.x + (pxRect.minX() - pt.x) / factor;
|
||||
endPt.x = pxRect.minX();
|
||||
}
|
||||
|
||||
if (pt.y != pxRect.maxY())
|
||||
{
|
||||
startPt.y = pt.y + ((pxRect.maxY() - pt.y) / factor);
|
||||
endPt.y = pxRect.maxY();
|
||||
}
|
||||
else
|
||||
{
|
||||
startPt.y = pt.y + (pxRect.minY() - pt.y) / factor;
|
||||
endPt.y = pxRect.minY();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Navigator::ScaleToPoint(m2::PointD const & pt, double factor, double /*timeInSec*/)
|
||||
{
|
||||
m2::PointD startPt;
|
||||
m2::PointD endPt;
|
||||
|
||||
m2::RectD const & pxRect = m_Screen.PixelRect();
|
||||
|
||||
// pt is in x0, x0 + width
|
||||
|
||||
if (pt.x != pxRect.maxX())
|
||||
{
|
||||
// start scaling point is 1 / factor way between pt and right border
|
||||
startPt.x = pt.x + ((pxRect.maxX() - pt.x) / factor);
|
||||
endPt.x = pxRect.maxX();
|
||||
}
|
||||
else
|
||||
{
|
||||
// start scaling point is 1 - 1/factor way between left border and pt
|
||||
startPt.x = pt.x + (pxRect.minX() - pt.x) / factor;
|
||||
endPt.x = pxRect.minX();
|
||||
}
|
||||
|
||||
if (pt.y != pxRect.maxY())
|
||||
{
|
||||
startPt.y = pt.y + ((pxRect.maxY() - pt.y) / factor);
|
||||
endPt.y = pxRect.maxY();
|
||||
}
|
||||
else
|
||||
{
|
||||
startPt.y = pt.y + (pxRect.minY() - pt.y) / factor;
|
||||
endPt.y = pxRect.minY();
|
||||
}
|
||||
|
||||
m2::PointD startPt, endPt;
|
||||
CalcScalePoints(pt, factor, m_Screen.PixelRect(), startPt, endPt);
|
||||
ScaleImpl(pt, endPt, pt, startPt, factor > 1, false);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class ZoomAnim : public anim::Task
|
||||
{
|
||||
public:
|
||||
typedef function<void (m2::PointD const &, m2::PointD const &,
|
||||
m2::PointD const &, m2::PointD const &)> scale_impl_fn;
|
||||
ZoomAnim(m2::PointD const & startPt, m2::PointD const & endPt,
|
||||
m2::PointD const & target, scale_impl_fn const & fn, double deltaTime)
|
||||
: m_targetPt(target)
|
||||
, m_startPt(startPt)
|
||||
, m_endPt(endPt)
|
||||
, m_prevPt(startPt)
|
||||
, m_fn(fn)
|
||||
, m_startTime(0.0)
|
||||
, m_deltaTime(deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool IsVisual() const { return true; }
|
||||
|
||||
void OnStart(double ts)
|
||||
{
|
||||
m_startTime = ts;
|
||||
}
|
||||
|
||||
void OnStep(double ts)
|
||||
{
|
||||
double elapsed = ts - m_startTime;
|
||||
if (my::AlmostEqual(elapsed, 0.0))
|
||||
return;
|
||||
|
||||
double t = elapsed / m_deltaTime;
|
||||
if (t > 1.0 || my::AlmostEqual(t, 1.0))
|
||||
{
|
||||
m_fn(m_targetPt, m_endPt, m_targetPt, m_prevPt);
|
||||
End();
|
||||
return;
|
||||
}
|
||||
|
||||
m2::PointD delta = (m_endPt - m_startPt) * t;
|
||||
m2::PointD current = m_startPt + delta;
|
||||
m_fn(m_targetPt, current, m_targetPt, m_prevPt);
|
||||
m_prevPt = current;
|
||||
}
|
||||
|
||||
private:
|
||||
m2::PointD m_targetPt;
|
||||
m2::PointD m_startPt;
|
||||
m2::PointD m_endPt;
|
||||
m2::PointD m_prevPt;
|
||||
|
||||
scale_impl_fn m_fn;
|
||||
double m_startTime;
|
||||
double m_deltaTime;
|
||||
};
|
||||
}
|
||||
|
||||
shared_ptr<anim::Task> Navigator::ScaleToPointAnim(m2::PointD const & pt, double factor, double timeInSec)
|
||||
{
|
||||
m2::PointD startPt, endPt;
|
||||
CalcScalePoints(pt, factor, m_Screen.PixelRect(), startPt, endPt);
|
||||
ZoomAnim * anim = new ZoomAnim(startPt, endPt, pt,
|
||||
bind(&Navigator::ScaleImpl, this, _1, _2, _3, _4, factor > 1, false),
|
||||
timeInSec);
|
||||
|
||||
return make_shared_ptr(anim);
|
||||
}
|
||||
|
||||
bool Navigator::CheckMinScale(ScreenBase const & screen) const
|
||||
{
|
||||
m2::RectD const & r = screen.ClipRect();
|
||||
|
@ -464,6 +538,8 @@ bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2,
|
|||
bool skipMinScaleAndBordersCheck,
|
||||
bool doRotateScreen)
|
||||
{
|
||||
LOG(LDEBUG, ("Start = ", oldPt2));
|
||||
LOG(LDEBUG, ("End = ", newPt2));
|
||||
math::Matrix<double, 3, 3> newM = m_Screen.GtoPMatrix() * ScreenBase::CalcTransform(oldPt1, oldPt2, newPt1, newPt2);
|
||||
|
||||
double oldAngle = m_Screen.GetAngle();
|
||||
|
@ -567,6 +643,11 @@ void Navigator::Scale(double scale)
|
|||
ScaleToPoint(m_Screen.PixelRect().Center(), scale, 0);
|
||||
}
|
||||
|
||||
shared_ptr<anim::Task> Navigator::ScaleAnim(double scale)
|
||||
{
|
||||
return ScaleToPointAnim(m_Screen.PixelRect().Center(), scale, 0.5);
|
||||
}
|
||||
|
||||
void Navigator::Rotate(double angle)
|
||||
{
|
||||
m_Screen.Rotate(angle);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
#include "scales_processor.hpp"
|
||||
|
||||
#include "../anim/task.hpp"
|
||||
|
||||
#include "../geometry/screenbase.hpp"
|
||||
|
||||
#include "../base/matrix.hpp"
|
||||
|
@ -8,7 +10,7 @@
|
|||
|
||||
#include "../std/function.hpp"
|
||||
#include "../std/scoped_ptr.hpp"
|
||||
|
||||
#include "../std/shared_ptr.hpp"
|
||||
|
||||
/// Calculates screen parameters in navigation (dragging, scaling, etc.).
|
||||
class Navigator
|
||||
|
@ -54,8 +56,10 @@ public:
|
|||
bool IsRotatingDuringScale() const;
|
||||
|
||||
void ScaleToPoint(m2::PointD const & pt, double factor, double timeInSec);
|
||||
shared_ptr<anim::Task> ScaleToPointAnim(m2::PointD const & pt, double factor, double timeInSec);
|
||||
|
||||
void Scale(double scale);
|
||||
shared_ptr<anim::Task> ScaleAnim(double scale);
|
||||
void Rotate(double angle);
|
||||
void SetAngle(double angle);
|
||||
void SetOrg(m2::PointD const & org);
|
||||
|
|
Loading…
Add table
Reference in a new issue