ui: add profile picture hover animation
I wanted to practice doing animation in egui, so here is a simple profile picture hover affect. When you mouse over a profile picture, it get slightly bigger. Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
19
src/ui/anim.rs
Normal file
19
src/ui/anim.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
pub fn hover_expand(
|
||||
ui: &mut egui::Ui,
|
||||
id: egui::Id,
|
||||
size: f32,
|
||||
expand_size: f32,
|
||||
anim_speed: f32,
|
||||
) -> (egui::Rect, f32) {
|
||||
// Allocate space for the profile picture with a fixed size
|
||||
let default_size = size + expand_size;
|
||||
let (rect, response) =
|
||||
ui.allocate_exact_size(egui::vec2(default_size, default_size), egui::Sense::hover());
|
||||
|
||||
let val = ui
|
||||
.ctx()
|
||||
.animate_bool_with_time(id, response.hovered(), anim_speed);
|
||||
|
||||
let size = size + val * expand_size;
|
||||
(rect, size)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod anim;
|
||||
pub mod note;
|
||||
pub mod preview;
|
||||
pub mod profile;
|
||||
|
||||
@@ -6,6 +6,7 @@ pub use options::NoteOptions;
|
||||
|
||||
use crate::{colors, ui, Damus};
|
||||
use egui::{Label, RichText, Sense};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
pub struct Note<'a> {
|
||||
app: &'a mut Damus,
|
||||
@@ -23,6 +24,20 @@ impl<'a> egui::Widget for Note<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
|
||||
struct ProfileAnimId {
|
||||
profile_key: u64,
|
||||
note_key: u64,
|
||||
}
|
||||
|
||||
impl Hash for ProfileAnimId {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_u8(0x12);
|
||||
self.profile_key.hash(state);
|
||||
self.note_key.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Note<'a> {
|
||||
pub fn new(app: &'a mut Damus, note: &'a nostrdb::Note<'a>) -> Self {
|
||||
let flags = NoteOptions::actionbar | NoteOptions::note_previews;
|
||||
@@ -104,7 +119,33 @@ impl<'a> Note<'a> {
|
||||
// these have different lifetimes and types,
|
||||
// so the calls must be separate
|
||||
Some(pic) => {
|
||||
ui.add(ui::ProfilePic::new(&mut self.app.img_cache, pic));
|
||||
let expand_size = 5.0;
|
||||
let anim_speed = 0.05;
|
||||
let profile_key = profile.as_ref().unwrap().record().note_key();
|
||||
let note_key = note_key.as_u64();
|
||||
|
||||
let (rect, size) = ui::anim::hover_expand(
|
||||
ui,
|
||||
egui::Id::new(ProfileAnimId {
|
||||
profile_key,
|
||||
note_key,
|
||||
}),
|
||||
ui::ProfilePic::default_size(),
|
||||
expand_size,
|
||||
anim_speed,
|
||||
);
|
||||
|
||||
ui.put(
|
||||
rect,
|
||||
ui::ProfilePic::new(&mut self.app.img_cache, pic).size(size),
|
||||
)
|
||||
.on_hover_ui_at_pointer(|ui| {
|
||||
ui.set_max_width(300.0);
|
||||
ui.add(ui::ProfilePreview::new(
|
||||
profile.as_ref().unwrap(),
|
||||
&mut self.app.img_cache,
|
||||
));
|
||||
});
|
||||
}
|
||||
None => {
|
||||
ui.add(ui::ProfilePic::new(
|
||||
|
||||
@@ -16,10 +16,14 @@ impl<'cache, 'url> egui::Widget for ProfilePic<'cache, 'url> {
|
||||
|
||||
impl<'cache, 'url> ProfilePic<'cache, 'url> {
|
||||
pub fn new(cache: &'cache mut ImageCache, url: &'url str) -> Self {
|
||||
let size = 32.0;
|
||||
let size = Self::default_size();
|
||||
ProfilePic { cache, url, size }
|
||||
}
|
||||
|
||||
pub fn default_size() -> f32 {
|
||||
32.0
|
||||
}
|
||||
|
||||
pub fn no_pfp_url() -> &'static str {
|
||||
"https://damus.io/img/no-profile.svg"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user