Rich image view smooth zoom

This commit is contained in:
Nikita Lisitsa 2021-03-05 20:09:15 +03:00
parent 2b2b2be560
commit 74423000cb
2 changed files with 20 additions and 9 deletions

View file

@ -36,6 +36,8 @@ namespace psemek::ui
struct shape const & shape() const override { return shape_; } struct shape const & shape() const override { return shape_; }
void reshape(geom::box<float, 2> const & bbox) override; void reshape(geom::box<float, 2> const & bbox) override;
void update(float dt) override;
void draw(painter & p) const override; void draw(painter & p) const override;
protected: protected:
@ -45,6 +47,7 @@ namespace psemek::ui
std::shared_ptr<gfx::texture_2d> image_; std::shared_ptr<gfx::texture_2d> image_;
geom::interval<float> zoom_range_ = {0.f, std::numeric_limits<float>::infinity()}; geom::interval<float> zoom_range_ = {0.f, std::numeric_limits<float>::infinity()};
float zoom_ = 1.f; float zoom_ = 1.f;
float zoom_tgt_ = 1.f;
geom::point<float, 2> center_{0.f, 0.f}; geom::point<float, 2> center_{0.f, 0.f};
bool allow_overflow_ = false; bool allow_overflow_ = false;
gfx::color_rgba color_{0, 0, 0, 0}; gfx::color_rgba color_{0, 0, 0, 0};

View file

@ -46,13 +46,8 @@ namespace psemek::ui
// (mouse - bbox.center) / zoom0 + center0 = (mouse - bbox.center) / zoom1 + center1 // (mouse - bbox.center) / zoom0 + center0 = (mouse - bbox.center) / zoom1 + center1
// center1 - center0 = (mouse - bbox.center) * (1 / zoom0 - 1 / zoom1) // center1 - center0 = (mouse - bbox.center) * (1 / zoom0 - 1 / zoom1)
auto new_center = center_; zoom_tgt_ = zoom;
set_center(center_);
if (mouse_)
new_center += (geom::cast<float>(*mouse_) - shape_.box.center()) * (1.f / zoom_ - 1.f / zoom);
zoom_ = zoom;
set_center(new_center);
} }
geom::box<float, 2> rich_image_view::region() const geom::box<float, 2> rich_image_view::region() const
@ -80,7 +75,6 @@ namespace psemek::ui
{ {
set_center(center_ + geom::cast<float>(*drag_ - e.position) / zoom_); set_center(center_ + geom::cast<float>(*drag_ - e.position) / zoom_);
drag_ = e.position; drag_ = e.position;
return true;
} }
return false; return false;
} }
@ -107,7 +101,7 @@ namespace psemek::ui
{ {
if (mouseover_) if (mouseover_)
{ {
set_zoom(zoom_ * std::pow(1.25f, e.delta)); set_zoom(zoom_tgt_ * std::pow(1.25f, e.delta));
return true; return true;
} }
return false; return false;
@ -137,6 +131,20 @@ namespace psemek::ui
post_region_changed(); post_region_changed();
} }
void rich_image_view::update(float dt)
{
float new_zoom = zoom_ + (zoom_tgt_ - zoom_) * std::min(1.f, dt * 20.f);
auto new_center = center_;
if (mouse_)
new_center += (geom::cast<float>(*mouse_) - shape_.box.center()) * (1.f / zoom_ - 1.f / new_zoom);
zoom_ = new_zoom;
set_center(new_center);
}
void rich_image_view::draw(painter & p) const void rich_image_view::draw(painter & p) const
{ {
auto st = merged_style(); auto st = merged_style();