When transforming large number of children blitz tend to lag at a way smaller amount than the webview
Platform tested: windows 11
use std::collections::HashMap;
use dioxus_native::prelude::dioxus_elements::geometry::ClientPoint;
use dioxus_native::prelude::*;
const COUNT: usize = 200;
pub fn main() {
dioxus_native::launch(app);
}
fn app() -> Element {
let mut viewport = use_store(Viewport::default);
let data = use_store(Data::default);
let mut position = use_store(|| ClientPoint::zero());
let onpointermove = move |evt: Event<PointerData>| {
let coords = evt.client_coordinates();
viewport.write().pan(&coords, &position.peek());
position.set(coords);
};
let onwheel = move |e: Event<WheelData>| {
let coords = e.client_coordinates();
let delta = e.delta().strip_units().y as f32;
viewport
.write()
.onscroll(coords.x as f32, coords.y as f32, delta);
};
rsx!(
style {
{CSS}
}
div {
tabindex: "-1",
position: "absolute",
top: 0,
left: 0,
width: "100vw",
height:"100vh",
onpointermove,
onwheel,
div {
border: "1px solid black",
position: "absolute",
top: 0,
left: 0,
transform_origin: "0 0",
width: 0,
height: 0,
transform: "{viewport}",
div {
for (id, item) in data.elements().iter() {
PositionedItem{
id: id,
data: item
}
}
}
}
}
)
}
#[component]
fn PositionedItem(id: usize, data: Store<PositinedElement>) -> Element {
rsx!(
div {
z_index: id,
pointer_events: "none",
user_select: "none",
position: "absolute",
border: "1px solid black",
left: format!("{}px", data.x()),
top: format!("{}px", data.y()),
width: format!("{}px", data.width()),
height: format!("{}px", data.height()),
div {
"Placed item {id}"
}
}
)
}
#[derive(Store, Clone, PartialEq)]
struct PositinedElement {
x: f32,
y: f32,
width: f32,
height: f32,
}
#[derive(Store, PartialEq)]
struct Data {
elements: HashMap<usize, PositinedElement>,
}
impl Default for Data {
fn default() -> Self {
Self {
elements: (0..COUNT)
.map(|i| {
(
i,
PositinedElement {
x: i as f32 * 30.0,
y: i as f32 * 20.0,
width: 60.0 + ((i * 37 + 11) % 100) as f32 * 0.8,
height: 60.0 + ((i * 53 + 7) % 100) as f32 * 0.8,
},
)
})
.collect(),
}
}
}
#[derive(Store, Debug, Clone, PartialEq)]
struct Viewport {
pan_x: f32,
pan_y: f32,
zoom: f32,
}
impl std::fmt::Display for Viewport {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"translate({}px, {}px) scale({})",
self.pan_x, self.pan_y, self.zoom
)
}
}
impl Default for Viewport {
fn default() -> Self {
Self {
pan_x: Default::default(),
pan_y: Default::default(),
zoom: 1.0,
}
}
}
impl Viewport {
fn pan(&mut self, screen: &ClientPoint, last: &ClientPoint) {
let dx = screen.x - last.x;
let dy = screen.y - last.y;
self.pan_x += dx as f32;
self.pan_y += dy as f32;
}
pub fn onscroll(&mut self, sx: f32, sy: f32, delta: f32) {
let factor = (1.0 + delta).clamp(0.8, 1.2);
let new_zoom = (self.zoom * factor).clamp(0.05, 50.0);
let wx = (sx - self.pan_x) / self.zoom;
let wy = (sy - self.pan_y) / self.zoom;
self.pan_x = sx - wx * new_zoom;
self.pan_y = sy - wy * new_zoom;
self.zoom = new_zoom;
}
}
const CSS: &str = r#"
* {
box-sizing: border-box;
}
html,
body,
main {
width: 100vw;
height: 100vh;
margin: 0;
}
"#;
When transforming large number of children blitz tend to lag at a way smaller amount than the webview
Platform tested: windows 11
Blitz release count: 200
blitz.mp4
Webview release count: 3000
web.mp4