anim.rs (3431B)
1 use egui::{Pos2, Rect, Response, Sense}; 2 3 pub fn hover_expand( 4 ui: &mut egui::Ui, 5 id: egui::Id, 6 size: f32, 7 expand_size: f32, 8 anim_speed: f32, 9 ) -> (egui::Rect, f32, egui::Response) { 10 // Allocate space for the profile picture with a fixed size 11 let default_size = size + expand_size; 12 let (rect, response) = 13 ui.allocate_exact_size(egui::vec2(default_size, default_size), egui::Sense::click()); 14 15 let val = ui 16 .ctx() 17 .animate_bool_with_time(id, response.hovered(), anim_speed); 18 19 let size = size + val * expand_size; 20 (rect, size, response) 21 } 22 23 pub fn hover_expand_small(ui: &mut egui::Ui, id: egui::Id) -> (egui::Rect, f32, egui::Response) { 24 let size = 10.0; 25 let expand_size = 5.0; 26 let anim_speed = 0.05; 27 28 hover_expand(ui, id, size, expand_size, anim_speed) 29 } 30 31 pub static ICON_EXPANSION_MULTIPLE: f32 = 1.2; 32 pub static ANIM_SPEED: f32 = 0.05; 33 pub struct AnimationHelper { 34 rect: Rect, 35 center: Pos2, 36 response: Response, 37 animation_progress: f32, 38 expansion_multiple: f32, 39 } 40 41 impl AnimationHelper { 42 pub fn new( 43 ui: &mut egui::Ui, 44 animation_name: impl std::hash::Hash, 45 max_size: egui::Vec2, 46 ) -> Self { 47 let id = ui.id().with(animation_name); 48 let (rect, response) = ui.allocate_exact_size(max_size, Sense::click()); 49 50 let animation_progress = 51 ui.ctx() 52 .animate_bool_with_time(id, response.hovered(), ANIM_SPEED); 53 54 Self { 55 rect, 56 center: rect.center(), 57 response, 58 animation_progress, 59 expansion_multiple: ICON_EXPANSION_MULTIPLE, 60 } 61 } 62 63 pub fn new_from_rect( 64 ui: &mut egui::Ui, 65 animation_name: impl std::hash::Hash, 66 animation_rect: egui::Rect, 67 ) -> Self { 68 let id = ui.id().with(animation_name); 69 let response = ui.allocate_rect(animation_rect, Sense::click()); 70 71 let animation_progress = 72 ui.ctx() 73 .animate_bool_with_time(id, response.hovered(), ANIM_SPEED); 74 75 Self { 76 rect: animation_rect, 77 center: animation_rect.center(), 78 response, 79 animation_progress, 80 expansion_multiple: ICON_EXPANSION_MULTIPLE, 81 } 82 } 83 84 pub fn scale_1d_pos(&self, min_object_size: f32) -> f32 { 85 let max_object_size = min_object_size * self.expansion_multiple; 86 87 if self.response.is_pointer_button_down_on() { 88 min_object_size 89 } else { 90 min_object_size + ((max_object_size - min_object_size) * self.animation_progress) 91 } 92 } 93 94 pub fn scale_radius(&self, min_diameter: f32) -> f32 { 95 self.scale_1d_pos((min_diameter - 1.0) / 2.0) 96 } 97 98 pub fn get_animation_rect(&self) -> egui::Rect { 99 self.rect 100 } 101 102 pub fn center(&self) -> Pos2 { 103 self.rect.center() 104 } 105 106 pub fn take_animation_response(self) -> egui::Response { 107 self.response 108 } 109 110 // Scale a minimum position from center to the current animation position 111 pub fn scale_from_center(&self, x_min: f32, y_min: f32) -> Pos2 { 112 Pos2::new( 113 self.center.x + self.scale_1d_pos(x_min), 114 self.center.y + self.scale_1d_pos(y_min), 115 ) 116 } 117 118 pub fn scale_pos_from_center(&self, min_pos: Pos2) -> Pos2 { 119 self.scale_from_center(min_pos.x, min_pos.y) 120 } 121 }