Mejorado de Zoom y panning

This commit is contained in:
Miguel 2024-06-09 21:26:09 +02:00
parent 506ee16ae1
commit 77c9f3db5e
1 changed files with 67 additions and 9 deletions

View File

@ -8,6 +8,7 @@ using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using UserControl = System.Windows.Controls.UserControl; using UserControl = System.Windows.Controls.UserControl;
using CtrEditor.ObjetosSim; using CtrEditor.ObjetosSim;
using System.Windows.Threading; using System.Windows.Threading;
using System.Diagnostics;
namespace CtrEditor namespace CtrEditor
@ -25,6 +26,14 @@ namespace CtrEditor
private Image imagenDeFondo; private Image imagenDeFondo;
private DispatcherTimer _zoomTimer; 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 // Para los UserControl
private Point _startPointUserControl; private Point _startPointUserControl;
@ -40,6 +49,11 @@ namespace CtrEditor
{ {
InitializeComponent(); InitializeComponent();
_zoomTimer = new DispatcherTimer();
_zoomTimer.Interval = TimeSpan.FromMilliseconds(1);
_zoomTimer.Tick += ZoomTimer_Tick;
_stopwatch = new Stopwatch();
this.Loaded += MainWindow_Loaded; this.Loaded += MainWindow_Loaded;
ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel; ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel;
ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning; ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning;
@ -380,26 +394,70 @@ namespace CtrEditor
private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e) 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 tg = (TransformGroup)ImagenEnTrabajoCanvas.RenderTransform;
var st = (ScaleTransform)tg.Children.First(t => t is ScaleTransform); var st = (ScaleTransform)tg.Children.First(t => t is ScaleTransform);
var tt = (TranslateTransform)tg.Children.First(t => t is TranslateTransform); var tt = (TranslateTransform)tg.Children.First(t => t is TranslateTransform);
double zoomFactor = e.Delta > 0 ? 1.1 : 0.9; // Interpolación cuadrática para la desaceleración
Point cursorPosition = e.GetPosition(ImagenEnTrabajoCanvas); 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 relativeX = cursorPosition.X * st.ScaleX + tt.X;
var relativeY = cursorPosition.Y * st.ScaleY + tt.Y; var relativeY = cursorPosition.Y * st.ScaleY + tt.Y;
// Aplicar el zoom st.ScaleX = zoomFactor;
st.ScaleX *= zoomFactor; st.ScaleY = 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.X = relativeX - cursorPosition.X * st.ScaleX;
tt.Y = relativeY - cursorPosition.Y * st.ScaleY; tt.Y = relativeY - cursorPosition.Y * st.ScaleY;
e.Handled = true; // Evita el procesamiento adicional del evento
} }
private void ListaOs_SelectionChanged(object sender, SelectionChangedEventArgs e) private void ListaOs_SelectionChanged(object sender, SelectionChangedEventArgs e)