diff --git a/src/domain/chart/value_objects.rs b/src/domain/chart/value_objects.rs index 6d8f501..9a8e9ea 100644 --- a/src/domain/chart/value_objects.rs +++ b/src/domain/chart/value_objects.rs @@ -67,10 +67,10 @@ impl Viewport { pub fn zoom(&mut self, factor: f32, center_x: f32) { let current_range = self.time_range(); let new_range = current_range / factor as f64; - let center_time = self.start_time + current_range * center_x as f64; + let anchor_time = self.start_time + current_range * center_x as f64; - self.start_time = center_time - new_range / 2.0; - self.end_time = center_time + new_range / 2.0; + self.start_time = anchor_time - new_range * center_x as f64; + self.end_time = self.start_time + new_range; } /// Scale prices vertically diff --git a/tests/viewport.rs b/tests/viewport.rs index e208dd7..e2cd08c 100644 --- a/tests/viewport.rs +++ b/tests/viewport.rs @@ -16,6 +16,21 @@ fn zoom_changes_time_range() { assert!((vp.end_time - 75.0).abs() < 1e-6); } +#[wasm_bindgen_test] +fn zoom_preserves_cursor_anchor() { + let mut vp = Viewport { + start_time: 0.0, + end_time: 100.0, + min_price: 0.0, + max_price: 100.0, + width: 800, + height: 600, + }; + vp.zoom(2.0, 0.8); + assert!((vp.start_time - 40.0).abs() < 1e-6); + assert!((vp.end_time - 90.0).abs() < 1e-6); +} + #[wasm_bindgen_test] fn pan_moves_viewport() { let mut vp = Viewport { diff --git a/tests/zoom_centering.rs b/tests/zoom_centering.rs index 2f3e887..90fda4c 100644 --- a/tests/zoom_centering.rs +++ b/tests/zoom_centering.rs @@ -15,6 +15,6 @@ fn zoom_pan_moves_toward_center() { vp.zoom(2.0, 0.25); vp.pan(-0.25, 0.0); - assert!((vp.start_time + 12.5).abs() < 1e-6); - assert!((vp.end_time - 37.5).abs() < 1e-6); + assert!((vp.start_time - 0.0).abs() < 1e-6); + assert!((vp.end_time - 50.0).abs() < 1e-6); }