2010-11-18 18 views
10

Est-ce que quelqu'un connaît un moyen facile d'animer un mouvement de l'emplacement actuel d'une image à un nouvel emplacement (X, Y) en utilisant l'animation WPF sans XAML, 100% par programmation? Et sans référence à "this" (avec RegisterName etc). J'essaye de faire une classe d'extension pour qu'Image fasse des choses d'animation dessus. Il est assez facile de modifier les propriétés width et height à l'aide d'une animation, mais après avoir recherché l'animation d'un objet, il devient soudainement plus avancé. Comme il s'agit d'une classe d'extension, je n'aurai qu'une référence à l'objet Image réel et le X et Y que je veux le déplacer vers.WPF. Le moyen le plus simple de déplacer l'image vers (X, Y) par programmation?

public static void MoveTo(this Image targetControl, double X, double Y, double Width, double Height){ 
//code here 
... 
} 

Mise à jour:

Merci. Presque travailler. Il semble que GetTop et GetLeft retournent «NaN» non défini explicitement. Trouvé la solution dans ce post: Canvas.GetTop() returning NaN

public static void MoveTo(this Image target, double newX, double newY) { 
       Vector offset = VisualTreeHelper.GetOffset(target); 
       var top = offset.Y; 
       var left = offset.X; 
       TranslateTransform trans = new TranslateTransform(); 
       target.RenderTransform = trans; 
       DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromSeconds(10)); 
       DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromSeconds(10)); 
       trans.BeginAnimation(TranslateTransform.YProperty, anim1); 
       trans.BeginAnimation(TranslateTransform.XProperty, anim2); 
     } 

je devais échanger deux des valeurs (de) avec 0. Je suppose que cela doit être parce que, dans ce contexte, le coin supérieur gauche de l'image est l'origine? Mais maintenant ça marche.

+0

Merci pour la mise à jour. C'était agréable de voir un exemple de comment utiliser un vecteur. –

Répondre

20

Essayez ceci:

public static void MoveTo(this Image target, double newX, double newY) 
{ 
    var top = Canvas.GetTop(target); 
    var left = Canvas.GetLeft(target); 
    TranslateTransform trans = new TranslateTransform(); 
    target.RenderTransform = trans; 
    DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10)); 
    DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10)); 
    trans.BeginAnimation(TranslateTransform.XProperty,anim1); 
    trans.BeginAnimation(TranslateTransform.YProperty,anim2); 
} 
+2

Cela ne fonctionnera que si l'image est dans un canevas (obtenir les propriétés Haut et Gauche retournera 0 sinon). Si vous utilisez un Canvas, vous pouvez simplement définir les propriétés Canvas.Top et Canvas.Left pour le déplacer. Pour un autre type de conteneur, vous pouvez définir les marges (eurgh) ou, comme Dean l'a mentionné, utiliser une transformation translate. – Guy

+3

Presque fonctionnel. Les propriétés left et top devaient être obtenues à partir de VisualTreeHelper.GetOffset (target) à la place de GetTop et GetLeft retournaient 'NaN'. Un seul bug est parti. Le début de l'animation semble commencer au double de l'emplacement actuel. – Wolf5

+1

0 comme la valeur de la fixer. – Wolf5

3

Ici, il est ... Il change la taille et déplace un MediaElement sous la Canvas. Il suffit d'entrer vos paramètres:

Storyboard story = new Storyboard(); 
DoubleAnimation dbWidth = new DoubleAnimation(); 
dbWidth.From = mediaElement1.Width; 
dbWidth.To = 600; 
dbWidth.Duration = new Duration(TimeSpan.FromSeconds(.25)); 

DoubleAnimation dbHeight = new DoubleAnimation(); 
dbHeight.From = mediaElement1.Height; 
dbHeight.To = 400; 
dbHeight.Duration = dbWidth.Duration; 

story.Children.Add(dbWidth); 
Storyboard.SetTargetName(dbWidth, mediaElement1.Name); 
Storyboard.SetTargetProperty(dbWidth, new PropertyPath(MediaElement.WidthProperty)); 

story.Children.Add(dbHeight); 
Storyboard.SetTargetName(dbHeight, mediaElement1.Name); 
Storyboard.SetTargetProperty(dbHeight, new PropertyPath(MediaElement.HeightProperty)); 

DoubleAnimation dbCanvasX = new DoubleAnimation(); 
dbCanvasX.From = 0; 
dbCanvasX.To = 5; 
dbCanvasX.Duration = new Duration(TimeSpan.FromSeconds(.25)); 

DoubleAnimation dbCanvasY = new DoubleAnimation(); 
dbCanvasY.From = 0; 
dbCanvasY.To = 5; 
dbCanvasY.Duration = dbCanvasX.Duration; 

story.Children.Add(dbCanvasX); 
Storyboard.SetTargetName(dbCanvasX, mediaElement1.Name); 
Storyboard.SetTargetProperty(dbCanvasX, new PropertyPath(Canvas.LeftProperty)); 

story.Children.Add(dbCanvasY); 
Storyboard.SetTargetName(dbCanvasY, mediaElement1.Name); 
Storyboard.SetTargetProperty(dbCanvasY, new PropertyPath(Canvas.TopProperty)); 

story.Begin(this); 

<Viewbox Stretch="Uniform" StretchDirection="Both" SnapsToDevicePixels="True"> 
     <Grid Width="640" Height="480" Name="MainLayout" SnapsToDevicePixels="True" Background="Black"> 
      <Canvas Width="640" Height="480" Name="MainCanvas" SnapsToDevicePixels="True"> 
       <MediaElement Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" LoadedBehavior="Manual" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" /> 
       <Button Canvas.Left="294" Canvas.Top="196" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" /> 
      </Canvas> 
     </Grid> 
    </Viewbox> 

MISE À JOUR:

Au lieu de MediaElement utiliser cette ligne:

<Rectangle Height="171" HorizontalAlignment="Left" Name="mediaElement1" VerticalAlignment="Top" Width="337" Margin="166,140,0,0" Canvas.Left="-162" Canvas.Top="-140" Fill="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}" /> 

Et ne pas oublier de mettre le C# code à:

private void button1_Click(object sender, RoutedEventArgs e) {} 

Vous pouvez utiliser MediaElement aussi bien, mais vous devez définir un VideoClip voir quelque chose;)

+0

Ya, j'ai mis ce code dans un nouvel élément Window et ajouté le code C# à l'événement button_click. Le code fonctionne parfaitement bien, mais n'effectue pas d'animation. Ai-je manqué quelque chose? –

+1

@JohnC Oui c'est le cas. Vérifie ma réponse N'oubliez pas de voter ... –

+0

Je suis devenu un peu meilleur dans les animations WPF ces derniers jours. Je vais essayer à nouveau quand je rentre à la maison. –

1

Ce code est basé sur la réponse de @ DeanChalk.

Il se déplace un Image contenu dans un Canvas (RFID_Token) en diagonale du haut à droite à en bas à gauche, en position centrale au-dessus de l'autre dans un ImageCanvas (RFID_Reader).

<Canvas> 
    <Canvas x:Name="RFID_Reader_Canvas"> 
     <Image x:Name="RFID_Reader" Source="RFID-Reader.png" Height="456" Width="682" Canvas.Left="37" Canvas.Top="524"/> 
    </Canvas> 
    <Canvas x:Name="RFID_Token_Canvas"> 
     <Image x:Name="RFID_Token" Source="RFID-Token.png" Height="268" Width="343" Canvas.Left="874" Canvas.Top="70"/> 
    </Canvas> 
</Canvas> 

var StartX = Canvas.GetLeft(RFID_Token); 
var StartY = Canvas.GetTop(RFID_Token); 

var EndX = RFID_Reader.Width/2 + Canvas.GetLeft(RFID_Reader) - StartX - (RFID_Token.Width/2); 
var EndY = RFID_Reader.Height/2 + Canvas.GetTop(RFID_Reader) - StartY - (RFID_Token.Height/2); 

var AnimationX = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(1)); 
var AnimationY = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(1)); 

var Transform = new TranslateTransform(); 
RFID_Token_Canvas.RenderTransform = Transform; 

Transform.BeginAnimation(TranslateTransform.XProperty, AnimationX); 
Transform.BeginAnimation(TranslateTransform.YProperty, AnimationY); 
0

S'il vous plaît trouver une solution qui utilise les propriétés Gauche et Haut de toile pour la méthode d'extension.Voir le code suivant:

public static void MoveTo(this Image target, Point newP) 
    { 

     Point oldP = new Point(); 
     oldP.X = Canvas.GetLeft(target); 
     oldP.Y = Canvas.GetTop(target); 

     DoubleAnimation anim1 = new DoubleAnimation(oldP.X, newP.X, TimeSpan.FromSeconds(0.2)); 
     DoubleAnimation anim2 = new DoubleAnimation(oldP.Y, newP.Y , TimeSpan.FromSeconds(0.2)); 

     target.BeginAnimation(Canvas.LeftProperty , anim1); 
     target.BeginAnimation(Canvas.TopProperty, anim2); 

    } 
1

Je gardé avoir NaN ou 0 valeurs pour mes éléments imbriqués, voici une version modifiée de la réponse de Danny:

public void MoveTo(Canvas canvas, FrameworkElement target, FrameworkElement destination) 
    { 
     Point oldPoint = target.TransformToAncestor(canvas).Transform(new Point(0, 0)); 
     Point newPoint = destination.TransformToAncestor(canvas).Transform(new Point(0, 0)); 

     var EndX = destination.Width/2 + newPoint.X - oldPoint.X - (target.Width/2); 
     var EndY = destination.Height/2 + newPoint.Y - oldPoint.Y - (target.Height/2); 

     TranslateTransform trans = new TranslateTransform(); 
     target.RenderTransform = trans; 
     DoubleAnimation anim1 = new DoubleAnimation(0, EndX, TimeSpan.FromSeconds(0.3)); 
     DoubleAnimation anim2 = new DoubleAnimation(0, EndY, TimeSpan.FromSeconds(0.3)); 
     trans.BeginAnimation(TranslateTransform.XProperty, anim1); 
     trans.BeginAnimation(TranslateTransform.YProperty, anim2); 
    }