优化导航栏动画

This commit is contained in:
lsy 2025-01-10 21:10:21 +08:00
parent cd67ab3f2e
commit b75433cdbd

View File

@ -1,5 +1,4 @@
use super::Toggle; use super::Toggle;
use crate::utils::dom::{add_element_class, get_document, remove_element_class};
use crate::Route; use crate::Route;
use dioxus::{logger::tracing, prelude::*}; use dioxus::{logger::tracing, prelude::*};
use wasm_bindgen::{prelude::Closure, JsCast}; use wasm_bindgen::{prelude::Closure, JsCast};
@ -9,37 +8,36 @@ pub fn Navbar() -> Element {
let mut progress_signal = use_signal(|| 0); let mut progress_signal = use_signal(|| 0);
let mut progress_hover = use_signal(|| false); let mut progress_hover = use_signal(|| false);
// 监听滚动事件
use_effect(move || { use_effect(move || {
let window = web_sys::window().unwrap(); let window = web_sys::window().unwrap();
let document = get_document().unwrap(); let document = window.document().unwrap();
let document_element = document.document_element().unwrap(); let document_element = document.document_element().unwrap();
let closure: Closure<dyn FnMut(_)> = Closure::wrap(Box::new(move |_: web_sys::Event| {
if progress_hover() {
return;
}
let screen_height = document_element.scroll_height() as f64;
let inner_height = window.inner_height().unwrap().as_f64().unwrap();
let scrool_height = window.scroll_y().unwrap();
let max_scroll_height = screen_height - inner_height;
let percent = if max_scroll_height > 0.0 { let closure: Closure<dyn FnMut(_)> = {
scrool_height / max_scroll_height Closure::wrap(Box::new(move |_: web_sys::Event| {
} else { let screen_height = document_element.scroll_height() as f64;
0.0 let inner_height = window.inner_height().unwrap().as_f64().unwrap();
}; let scrool_height = window.scroll_y().unwrap();
let percent = (percent.clamp(0.0, 1.0) * 100.0) as i32; let max_scroll_height = screen_height - inner_height;
if percent > 0 {
let _ = remove_element_class("nav .progress", "hidden"); let percent = if max_scroll_height > 0.0 {
} else { scrool_height / max_scroll_height
let _ = add_element_class("nav .progress", "hidden"); } else {
} 0.0
progress_signal.set(percent); };
}) as Box<dyn FnMut(_)>); let percent = (percent.clamp(0.0, 1.0) * 100.0) as i32;
progress_signal.set(percent);
}) as Box<dyn FnMut(_)>)
};
document document
.add_event_listener_with_callback("scroll", closure.as_ref().unchecked_ref()) .add_event_listener_with_callback("scroll", closure.as_ref().unchecked_ref())
.unwrap(); .unwrap();
closure.forget(); closure.forget();
}); });
rsx! { rsx! {
nav { nav {
class: "border-red-500 bg-slate-400 text-xl fixed top-0 left-0 right-0", class: "border-red-500 bg-slate-400 text-xl fixed top-0 left-0 right-0",
@ -75,29 +73,37 @@ pub fn Navbar() -> Element {
width: 30 width: 30
} }
div { div {
class:"progress bg-accent h-7 p-2 rounded-full text-xs flex items-center justify-center min-w-7 transition-all duration-300 hidden", class: "progress bg-accent h-7 rounded-full text-xs flex items-center justify-center transition-all duration-300 overflow-hidden",
onmouseenter:move|_|{ style: if progress_signal() > 0 {
format!("opacity: 1; transform: translateX(0); width: {}px;", if progress_signal()==100 { "70" } else { "28" })
} else {
"opacity: 0; transform: translateX(100%); width: 0px".to_string()
},
onmouseenter: move |_| {
progress_hover.set(true); progress_hover.set(true);
}, },
onmouseleave:move|_|{ onmouseleave: move |_| {
progress_hover.set(false); progress_hover.set(false);
}, },
onclick:move|_|{ onclick: move |_| {
progress_hover.set(false); progress_hover.set(false);
let window = web_sys::window().unwrap(); let window = web_sys::window().unwrap();
window.scroll_to_with_x_and_y(0.0, 0.0); window.scroll_to_with_x_and_y(0.0, 0.0);
}, },
{ div {
if progress_hover(){ class: "px-2 whitespace-nowrap transition-opacity duration-150",
"".to_string() style: "opacity: 1",
} {
else{ if progress_hover() {
if progress_signal()==100{ "".to_string()
"返回顶部".to_string()
} }
else { else{
progress_signal().to_string() if progress_signal()==100 {
"返回顶部".to_string()
}
else {
progress_signal().to_string()
}
} }
} }
} }