Transforms lag significantly sooner than in webview
- Dominant language
- Rust
- Stars
- 4.1k
- Forks
- 203
- Avg merge
- 8h 58m
- Merged PRs (30d)
- 112
Description
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**
https://github.com/user-attachments/assets/d24c23e4-75d4-4ea2-bf84-57651724f822
Webview release count: **3000**
https://github.com/user-attachments/assets/3670349e-4145-43b8-8ec2-b3c47d9f8cdf
```rust
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| {
let coords = evt.client_coordinates();
viewport.write().pan(&coords, &position.peek());
position.set(coords);
};
let onwheel = move |e: Event| {
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) -> 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,
}
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;
}
"#;
```
Contributor guide
Research direction
Start by running the supplied Rust reproduction on Windows 11 and compare how many transformed children remain responsive in Blitz versus the webview. Investigate the transform and rendering path exposed by this example; done means large child counts no longer make Blitz lag substantially earlier than the reported webview baseline.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100