Zoom

De Banane Atomic
Aller à la navigationAller à la recherche

Zoom

Le premier canvas doit être clippé et transparent. Quant au second, il contiendra tous les éléments à afficher. C'est sur ce dernier que les transformations de zoom seront appliquées.

Xaml.png
<Canvas ClipToBounds="True" Background="Transparent">
    <Canvas Name="petitCanvas">
        ...
    </Canvas>
</Canvas>

Zoom roulette

Csharp.svg
void MainWindow_MouseWheel(object sender, MouseWheelEventArgs e)
{
    double ratio = (e.Delta > 0) ? 1.1 : 0.9;  // zoom in ou zoom out
    var matrix = petitCanvas.RenderTransform.Value;
    var grandCanvas = (FrameworkElement)petitCanvas.Parent;

    matrix.ScaleAt(ratio, ratio, grandCanvas.ActualWidth / 2d, grandCanvas.ActualHeight / 2d);
    petitCanvas.RenderTransform = new MatrixTransform(matrix);
}

Zoom avec rectangle de sélection

Csharp.svg
void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.LeftButton == MouseButtonState.Pressed)
    {  // dessin du rectangle de sélection
        _selection = new Rectangle();
        _selection.Stroke = Brushes.Blue;
        Brush fillBrush = Brushes.Blue.Clone();
        fillBrush.Opacity = 0.2d;
        _selection.Fill = fillBrush;
        _selection.StrokeThickness = 1;
        petitCanvas.Children.Add(_selection);
        _originOfSelection = e.GetPosition(petitCanvas);
        Canvas.SetLeft(_selection, _originOfSelection.X);
        Canvas.SetTop(_selection, _originOfSelection.Y);
        petitCanvas.CaptureMouse();
    }
}

void MainWindow_MouseMove(object sender, MouseEventArgs e)
{
    if (_selection != null)
    {  // changement de taille du rectangle de sélection
        var position = e.GetPosition(petitCanvas);
        Canvas.SetLeft(_selection, Math.Min(p.X, _originOfSelection.X));
        Canvas.SetTop(_selection, Math.Min(p.Y, _originOfSelection.Y));
        _selection.Width = Math.Abs(p.X - _originOfSelection.X);
        _selection.Height = Math.Abs(p.Y - _originOfSelection.Y);
    }
}

void MainWindow_MouseUp(object sender, MouseButtonEventArgs e)
{
    if (selection != null)
    {
        Rect selectionRect = new Rect(
            Canvas.GetLeft(selection), Canvas.GetTop(selection),
            selection.Width, selection.Height);
        ZoomFit(selectionRect);
        petitCanvas.Children.Remove(selection);
        selection = null;
        petitCanvas.ReleaseMouseCapture();
    }
}

public void ZoomFit(Rect sourceRect)
{
    var grandCanvas = (FrameworkElement)petitCanvas.Parent;
    var destinationSize = new Size(grandCanvas.ActualWidth, grandCanvas.ActualHeight);

    double w = destinationSize.Width / sourceRect.Width;
    double h = destinationSize.Height / sourceRect.Height;
    double ratio = Math.Min(w, h);

    double dx = -(sourceRect.Left + sourceRect.Width / 2);
    double dy = -(sourceRect.Top + sourceRect.Height / 2);

    var matrix = new Matrix();
    matrix.Translate(dx, dy);
    matrix.Scale(ratio, ratio);
    matrix.Translate(destinationSize.Width / 2, destinationSize.Height / 2);

    petitCanvas.RenderTransform = new MatrixTransform(matrix);
}

Zoom contenu

Csharp.svg
// GetDescendantBounds renvoit le plus petit rectangle
// contenant l'ensemble des éléments de petitCanvas
ZoomFit(VisualTreeHelper.GetDescendantBounds(petitCanvas));

Déplacement du petit canvas

Csharp.svg
void MainWindow_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.MiddleButton == MouseButtonState.Pressed)
    {
        _originOfMove = e.GetPosition((FrameworkElement)petitCanvas.Parent);
        _canStartMove = true;
    }
}

void MainWindow_MouseMove(object sender, MouseEventArgs e)
{
    if (_canStartMove)
    {
        var nextOrigin = e.GetPosition((FrameworkElement)petitCanvas.Parent);
        var matrix = petitCanvas.RenderTransform.Value;
        var v = nextOrigin - _originOfMove;
        matrix.Translate(v.X, v.Y);
        petitCanvas.RenderTransform = new MatrixTransform(matrix);
        _originOfMove = nextOrigin;
    }
}

void MainWindow_MouseUp(object sender, MouseButtonEventArgs e)
{
    _canStartMove = false;
}