leptos_use/use_device_pixel_ratio.rs
1use cfg_if::cfg_if;
2use leptos::prelude::*;
3
4/// Reactive [`window.devicePixelRatio`](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio)
5///
6/// > NOTE: there is no event listener for `window.devicePixelRatio` change.
7/// > So this function uses the same mechanism as described in
8/// > [this example](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#monitoring_screen_resolution_or_zoom_level_changes).
9///
10/// ## Demo
11///
12/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_device_pixel_ratio)
13///
14/// ## Usage
15///
16/// ```
17/// # use leptos::prelude::*;
18/// # use leptos_use::use_device_pixel_ratio;
19/// #
20/// # #[component]
21/// # fn Demo() -> impl IntoView {
22/// let pixel_ratio = use_device_pixel_ratio();
23/// #
24/// # view! { }
25/// # }
26/// ```
27///
28/// ## Server-Side Rendering
29///
30/// > Make sure you follow the [instructions in Server-Side Rendering](https://leptos-use.rs/server_side_rendering.html).
31///
32/// On the server this function returns a Signal that is always `1.0`.
33pub fn use_device_pixel_ratio() -> Signal<f64> {
34 cfg_if! { if #[cfg(feature = "ssr")] {
35 Signal::derive(|| 1.0)
36 } else {
37 use crate::{use_event_listener_with_options, UseEventListenerOptions};
38
39 use leptos::ev::change;
40
41 let initial_pixel_ratio = window().device_pixel_ratio();
42 let (pixel_ratio, set_pixel_ratio) = signal(initial_pixel_ratio);
43
44 Effect::new(move |_| {
45 let media = window().match_media(
46 &format!("(resolution: {}dppx)", pixel_ratio.get())
47 ).unwrap();
48
49 _ = use_event_listener_with_options(
50 media,
51 change,
52 move |_| {
53 set_pixel_ratio.set(window().device_pixel_ratio());
54 },
55 UseEventListenerOptions::default()
56 .capture(false)
57 .passive(true)
58 .once(true),
59 );
60 });
61
62 pixel_ratio.into()
63 }}
64}