diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 6a29038..c5966cd 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -8,6 +8,7 @@ using MouseEventArgs = System.Windows.Input.MouseEventArgs; using UserControl = System.Windows.Controls.UserControl; using CtrEditor.ObjetosSim; using System.Windows.Threading; +using System.Diagnostics; namespace CtrEditor @@ -25,6 +26,14 @@ namespace CtrEditor private Image imagenDeFondo; private DispatcherTimer _zoomTimer; + private double _targetZoomFactor; + private double _initialZoomFactor; + private double _currentZoomStep; + private Point _zoomCursorPosition; + private const int ZoomDuration = 500; // Duración del zoom en milisegundos + private int _ZoomDuration; + private const double MinZoomScale = 0.1; // Límite mínimo de zoom + private Stopwatch _stopwatch; // Para los UserControl private Point _startPointUserControl; @@ -40,6 +49,11 @@ namespace CtrEditor { InitializeComponent(); + _zoomTimer = new DispatcherTimer(); + _zoomTimer.Interval = TimeSpan.FromMilliseconds(1); + _zoomTimer.Tick += ZoomTimer_Tick; + _stopwatch = new Stopwatch(); + this.Loaded += MainWindow_Loaded; ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel; ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning; @@ -380,26 +394,70 @@ namespace CtrEditor private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e) { + _initialZoomFactor = ((ScaleTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform).Children.First(t => t is ScaleTransform)).ScaleX; + + // Calcula el factor de escala mínimo para que toda la imagen sea visible + double minZoomFactor = Math.Min( + ImagenEnTrabajoScrollViewer.ViewportWidth / ImagenEnTrabajoCanvas.ActualWidth, + ImagenEnTrabajoScrollViewer.ViewportHeight / ImagenEnTrabajoCanvas.ActualHeight); + + // Ajusta el targetZoomFactor pero no permite que baje del mínimo + _targetZoomFactor = e.Delta > 0 ? _initialZoomFactor * 1.4 : Math.Max(_initialZoomFactor * 0.75, minZoomFactor); + + _zoomCursorPosition = e.GetPosition(ImagenEnTrabajoCanvas); + + // Desactivar el escalado de alta calidad para mejorar el rendimiento + RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.LowQuality); + + if (!_zoomTimer.IsEnabled) + _ZoomDuration = ZoomDuration; + else + _ZoomDuration = ZoomDuration / 3; + + _stopwatch.Restart(); + _zoomTimer.Start(); + + e.Handled = true; + } + + + private void ZoomTimer_Tick(object sender, EventArgs e) + { + double elapsedMilliseconds = _stopwatch.ElapsedMilliseconds; + + if (elapsedMilliseconds >= _ZoomDuration) + { + _zoomTimer.Stop(); + _stopwatch.Stop(); + + // Volver a activar el escalado de alta calidad después de completar el zoom + RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.HighQuality); + + return; + } + var tg = (TransformGroup)ImagenEnTrabajoCanvas.RenderTransform; var st = (ScaleTransform)tg.Children.First(t => t is ScaleTransform); var tt = (TranslateTransform)tg.Children.First(t => t is TranslateTransform); - double zoomFactor = e.Delta > 0 ? 1.1 : 0.9; - Point cursorPosition = e.GetPosition(ImagenEnTrabajoCanvas); + // Interpolación cuadrática para la desaceleración + double t = elapsedMilliseconds / _ZoomDuration; + double easeOutT = t * (2 - t); // Función de interpolación cuadrática (ease-out) + double zoomFactor = _initialZoomFactor + (_targetZoomFactor - _initialZoomFactor) * easeOutT; + + // Asegúrate de no ir por debajo del zoom mínimo + zoomFactor = Math.Max(zoomFactor, MinZoomScale); + + Point cursorPosition = _zoomCursorPosition; - // Calcular el punto focal del zoom relativo al contenido del Canvas var relativeX = cursorPosition.X * st.ScaleX + tt.X; var relativeY = cursorPosition.Y * st.ScaleY + tt.Y; - // Aplicar el zoom - st.ScaleX *= zoomFactor; - st.ScaleY *= zoomFactor; + st.ScaleX = zoomFactor; + st.ScaleY = zoomFactor; - // Ajustar la transformación de traducción para mantener el punto de zoom centrado tt.X = relativeX - cursorPosition.X * st.ScaleX; tt.Y = relativeY - cursorPosition.Y * st.ScaleY; - - e.Handled = true; // Evita el procesamiento adicional del evento } private void ListaOs_SelectionChanged(object sender, SelectionChangedEventArgs e)