web_scroll.rs 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637
  1. use gloo::render::{request_animation_frame, AnimationFrame};
  2. use log::error;
  3. use serde::{Deserialize, Serialize};
  4. use wasm_bindgen::JsValue;
  5. use web_sys::{History, Window};
  6. #[derive(Debug, Default, Deserialize, Serialize)]
  7. pub(crate) struct ScrollPosition {
  8. x: f64,
  9. y: f64,
  10. }
  11. pub(crate) fn top_left() -> JsValue {
  12. serde_wasm_bindgen::to_value(&ScrollPosition::default()).unwrap()
  13. }
  14. pub(crate) fn update_history(window: &Window, history: &History) {
  15. let position = serde_wasm_bindgen::to_value(&ScrollPosition {
  16. x: window.scroll_x().unwrap_or_default(),
  17. y: window.scroll_y().unwrap_or_default(),
  18. })
  19. .unwrap();
  20. if let Err(e) = history.replace_state(&position, "") {
  21. error!("failed to update scroll position: {e:?}");
  22. }
  23. }
  24. pub(crate) fn update_scroll(window: &Window, history: &History) -> AnimationFrame {
  25. let ScrollPosition { x, y } = history
  26. .state()
  27. .map(|state| serde_wasm_bindgen::from_value(state).unwrap_or_default())
  28. .unwrap_or_default();
  29. let w = window.clone();
  30. request_animation_frame(move |_| w.scroll_to_with_x_and_y(x, y))
  31. }