web-dev-qa-db-fra.com

WPF. Le moyen le plus simple de déplacer Image vers (X, Y) par programme?

Est-ce que quelqu'un connaît un moyen simple d'animer un mouvement de l'emplacement actuel d'une image vers un nouvel emplacement (X, Y) à l'aide d'une animation WPF sans XAML, 100% par programme? Et sans référence à "this" (avec RegisterName, etc.).

J'essaie de créer une classe d'extension pour que Image puisse y créer des éléments d'animation. Il est assez facile de modifier les propriétés width et height via une animation, mais après avoir recherché l'animation de localisation d'un objet, celle-ci devient soudainement plus avancée.

Comme il s'agit d'une classe d'extension, je n'aurai qu'une référence à l'objet Image réel et aux X et Y vers lesquels je souhaite le déplacer.

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 ne renvoie pas 'NaN' explicitement. J'ai trouvé la solution de contournement dans cet article: Canvas.GetTop () retournant 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);
        }

J'ai dû permuter deux des valeurs (FROM) 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.

11
Wolf5

Essaye ça:

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);
}
22
Dean Chalk

La voici ... Elle change la taille et déplace une MediaElement sous la Canvas. Il suffit de saisir 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>

METTRE À JOUR:

Au lieu de MediaElement, utilisez 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 n'oubliez pas de mettre le code C # dans: 

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

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

4

J'ai gardé NaN ou 0 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);
    }
1
Akli

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

Il déplace une Image contenue dans une Canvas (RFID_Token) en diagonale du haut à droite du bas à gauche, positionnée au centre d'une autre Image dans une Canvas (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);
1
Danny Beckett

Veuillez trouver une solution utilisant les propriétés Left et Top de Canvas 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);

    }
0
laserman