diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 4be07c56ec..1039f30aa8 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -251,10 +251,15 @@ pub extern "C" fn set_view_end() { state.render_state.options.set_fast_mode(false); // We can have renders in progress state.render_state.cancel_animation_frame(); - if state.render_state.options.is_profile_rebuild_tiles() { - state.rebuild_tiles(); - } else { - state.rebuild_tiles_shallow(); + // Only rebuild tile indices when zoom has changed. + // During pan-only operations, shapes stay in the same tiles + // because tile_size = 1/scale * TILE_SIZE (depends only on zoom). + if state.render_state.zoom_changed() { + if state.render_state.options.is_profile_rebuild_tiles() { + state.rebuild_tiles(); + } else { + state.rebuild_tiles_shallow(); + } } }); } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 8f789fd663..cc743f79af 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -2057,6 +2057,12 @@ impl RenderState { self.cached_viewbox.zoom() * self.options.dpr() } + /// Returns true if the zoom level has changed since the last cached viewbox. + /// Used to optimize pan-only operations where tile indices don't need to be rebuilt. + pub fn zoom_changed(&self) -> bool { + (self.viewbox.zoom - self.cached_viewbox.zoom).abs() > f32::EPSILON + } + pub fn mark_touched(&mut self, uuid: Uuid) { self.touched_ids.insert(uuid); }