Skip to main content

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}