2010-03-03 6 views
4

Im écrire une application WPF qui a un zoom et pan capacité, mais ce que je veux également mettre en œuvre est la possibilité de zoomer et de panoramique "automatiquement" (via un clic de bouton). J'ai les méthodes toutes définies pour zoomer et faire un panoramique, mais j'ai du mal à dire à l'application les coordonnées X/Y souhaitées pour le panoramique. Fondamentalement, je sais que je veux que le contrôle soit centré à un niveau de zoom désiré (par exemple 6x fois zoomé), mais le point de destination panoramique n'est pas le point central du contrôle car après le zoom, il a été mis à l'échelle .Comment pouvez-vous calculer la coordonnée X/Y pour zoomer

Est-ce que quelqu'un connaît un moyen de calculer la position X/Y souhaitée pour effectuer un panoramique, en tenant compte également du zoom? Dois-je simplement mettre à l'échelle le point de destination souhaité? Il ne semble pas fonctionner pour moi ...

Merci beaucoup

EDIT - Complété -

Voici maintenant ce que j'ai qui fonctionne très bien :)

<Canvas x:Name="LayoutRoot" Background="{DynamicResource WindowBackground}" Width="1024" Height="768"> 
    <Canvas x:Name="ProductCanvas" Width="1024" Height="768"> 
     <Canvas.RenderTransform> 
      <TransformGroup> 
       <ScaleTransform/> 
       <SkewTransform/> 
       <RotateTransform/> 
       <TranslateTransform /> 
      </TransformGroup> 
     </Canvas.RenderTransform> 
     <Rectangle x:Name="r1" Fill="White" Stroke="Black" Width="180" Height="103.5" Canvas.Left="131.5" Canvas.Top="121.5" MouseDown="r1_MouseDown"/> 
     <Rectangle x:Name="r2" Fill="#FF942222" Stroke="Black" Width="180" Height="103.5" Canvas.Left="617.5" Canvas.Top="121.5" MouseDown="r2_MouseDown"/> 
     <Rectangle x:Name="r3" Fill="#FF2B1E9F" Stroke="Black" Width="180" Height="103.5" Canvas.Left="131.5" Canvas.Top="408" MouseDown="r3_MouseDown"/> 
     <Rectangle x:Name="r4" Fill="#FF1F6E1D" Stroke="Black" Width="180" Height="103.5" Canvas.Left="617.5" Canvas.Top="408" MouseDown="r4_MouseDown"/> 
    </Canvas> 
    </Canvas> 

---- C# ----

private void r1_MouseDown(object sender, MouseButtonEventArgs e1) 
    { 
     Rect bounds = r1.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r1.ActualWidth, r1.ActualHeight)); 
     ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width/2), bounds.TopLeft.Y + (bounds.Height/2))); 
    } 

    private void r2_MouseDown(object sender, MouseButtonEventArgs e1) 
    { 
     Rect bounds = r2.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r2.ActualWidth, r2.ActualHeight)); 
     ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width/2), bounds.TopLeft.Y + (bounds.Height/2))); 
    } 

    private void r3_MouseDown(object sender, MouseButtonEventArgs e1) 
    { 
     Rect bounds = r3.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r3.ActualWidth, r3.ActualHeight)); 
     ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width/2), bounds.TopLeft.Y + (bounds.Height/2))); 
    } 

    private void r4_MouseDown(object sender, MouseButtonEventArgs e1) 
    { 
     Rect bounds = r4.TransformToAncestor(ProductCanvas).TransformBounds(new Rect(0, 0, r4.ActualWidth, r4.ActualHeight)); 
     ZoomInAndPan(5, new Point(bounds.TopLeft.X + (bounds.Width/2), bounds.TopLeft.Y + (bounds.Height/2))); 
    } 

    public void ZoomInAndPan(double zoomTo, Point translateTarget) 
    { 
     var group = (ProductCanvas.RenderTransform as TransformGroup); 

     var zoomTransform = group.Children[0] as ScaleTransform; 
     var translateTransform = group.Children[3] as TranslateTransform; 

     Point center = new Point(512, 384); 

     destinationPoint.X *= newScale; 
     destinationPoint.Y *= newScale; 

     var deltaX = center.X - (translateTarget.X); 
     var deltaY = center.Y - (translateTarget.Y); 

     translateTransform.BeginAnimation(TranslateTransform.XProperty, CreateZoomAnimation(deltaX)); 
     translateTransform.BeginAnimation(TranslateTransform.YProperty, CreateZoomAnimation(deltaY)); 

     zoomTransform.BeginAnimation(ScaleTransform.ScaleXProperty, CreateZoomAnimation(zoomTo)); 
     zoomTransform.BeginAnimation(ScaleTransform.ScaleYProperty, CreateZoomAnimation(zoomTo)); 
    } 

    private DoubleAnimation CreateZoomAnimation(double toValue) 
    { 
     var da = new DoubleAnimation(toValue, new Duration(TimeSpan.FromMilliseconds(700))) 
     { 
      AccelerationRatio = 0.1, 
      DecelerationRatio = 0.9 
     }; 

     return da; 
    } 

Répondre

5

Vous parlez d'une transformation - une casserole et une échelle.

Vous pouvez le faire de différentes façons, mais puisque vous utilisez WPF, y a-t-il une raison pour laquelle vous ne pouvez pas utiliser RenderTransforms?

var pointClicked = (where user clicked) 
var myWindow = (whatever your window is); 

myWindow.RenderTransform = new TransformGroup(); 
var pan = new TranslateTransform(pointClicked.X, pointClicked.Y); 
var scale = new ScaleTransform(6.0,6.0); 
myWindow.RenderTransform.Children.Add(pan); 
myWindow.RenderTransform.Children.Add(scale); 

Si vous ne voulez pas aller dans cette voie, vous devez faire la transformation 2D « à la main »: mais faire la casserole, puis l'échelle. Les transformations ne sont généralement pas communicatives. vous obtiendrez de mauvais résultats si vous les faites dans un ordre différent.

+0

J'ai les transformations qui fonctionnent bien, je suis question que je ne peux pas calculer la traduction X/Y souhaitée afin d'obtenir un point de pan dans le centre de l'écran. – Mark

+0

C'est ce à quoi je faisais référence dans l'ordre des opérations - avez-vous essayé d'abord la traduction (c.-à-d., Nouveau centre = clickpoint.X, clickpoint.Y) et ensuite exécuté l'échelle? – JerKimball

+0

En d'autres termes: si je clique sur le point (50,50), je dois d'abord recentrer ma vue sur le point (50,50), puis effectuer la mise à l'échelle du zoom. Si vous le faites dans l'autre sens, afin de traduire au bon endroit, vous devrez transformer la traduction originale par l'échelle ... cela semble plus confus que c'est.Fondamentalement, afin de comprendre le post-scalaire deltaX/deltaY, vous devez prendre ce que le deltaX/deltaY * aurait été *, puis mettre à l'échelle ce vecteur par votre transformation de zoom. – JerKimball

1

Au départ, vous r viewport est à (0,0) et l'image et la fenêtre sont toutes deux de taille X par Y. Vous souhaitez agrandir la taille par un facteur de grossissement, m afin que vos images soient de taille m X par m Y, mais votre viewport (la partie que vous montrez) est toujours un rectangle de taille X par Y, positionné à (0,0) sur l'image. Donc vous devez déplacer le port de vue.

Si votre image est maintenant m X par m Y, vous pouvez trouver les points milieu en les divisant par deux. Vous pouvez ensuite soustraire la moitié de la taille de la fenêtre pour obtenir le coin supérieur gauche. Quelque chose comme (m X/2 - X/2, m Y/2 - Y/2).

+0

Je comprends ce que vous dites, cependant, je suis encore confus quant à la façon de calculer la traduction désirée afin d'animer cette traduction de sorte que le point désiré est au centre de l'écran. – Mark

Questions connexes