2010-11-18 11 views
10

Czy ktoś wie o łatwym sposobie animowania ruchu z bieżącej lokalizacji obrazu do nowej lokalizacji (X, Y) przy użyciu animacji WPF bez XAML, programowo 100%? I bez odniesienia do "this" (z RegisterName itp.).WPF. Najłatwiejszy sposób programowego przeniesienia obrazu do (X, Y)?

Próbuję utworzyć klasę rozszerzenia dla obrazu, aby robić na nim animacje. Łatwo jest zmienić właściwości szerokości i wysokości za pomocą animacji, ale po wyszukaniu animacji położenia obiektu staje się on nagle bardziej zaawansowany.

Ponieważ jest to klasa rozszerzenia, odwołuję się tylko do rzeczywistego obiektu Image oraz do X i Y, do których chcę go przenieść.

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

Aktualizacja:

Dzięki. Prawie działa. Wygląda na to, że GetTop i GetLeft nie zwracają wyraźnie "NaN". Znaleziono obejście w tym poście: 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); 
     } 

musiałem zamienić dwie wartości (Z) 0. Zakładam, że musi być, ponieważ w tym kontekście, że lewy górny róg obrazu jest pochodzenie? Ale teraz działa.

+0

Dzięki za aktualizację. Miło było zobaczyć przykład użycia Vectora. –

Odpowiedz

20

Spróbuj tego:

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

Działa to tylko wtedy, gdy obraz znajduje się wewnątrz płótna (uzyskanie właściwości Góra i Lewy spowoduje powrót 0 w przeciwnym razie). Jeśli używasz Canvas, możesz po prostu ustawić właściwości Canvas.Top i Canvas.Left, aby go przenieść. Dla innego typu kontenera możesz ustawić marginesy (eurgh) lub jak wspomniał Dean, użyj transformaty translate. – Guy

+3

Prawie działa. Właściwości left i top musiały zostać pobrane z VisualTreeHelper.GetOffset (target) zamiast GetTop, a GetLeft zwróciło "NaN". Pozostał tylko jeden błąd. Początek animacji zaczyna się od podwójnej bieżącej lokalizacji. – Wolf5

+1

0 jako wartość z poprawiono. – Wolf5

3

Oto ona ... To zmienia rozmiar i przesuwa MediaElement pod Canvas. Wystarczy wpisać swoje parametry:

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> 

UPDATE:

Zamiast MediaElement wykorzystania tej linii:

<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}}" /> 

i nie zapomnij umieścić C# kod do:

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

Można użyć MediaElement jak dobrze, ale trzeba zdefiniować VideoClip zobaczyć coś;)

+0

Tak, umieściłem ten kod w nowym elemencie Window i dodałem kod C# do zdarzenia button_click. Kod działa idealnie dobrze, ale nie wykonuje animacji. Przegapiłem coś? –

+1

@JohnC Tak, tak. Sprawdź moją odpowiedź. Nie zapomnij o głosowaniu ... –

+0

Stałem się trochę lepszy w animacjach WPF w ciągu ostatnich kilku dni. Spróbuję ponownie, kiedy wrócę do domu. –

1

Kod ten jest oparty na użytkownika @ DeanChalk odpowiedź.

Porusza się Image zawartego w Canvas (RFID_Token) ukośnie od góry po prawej stronie na dole po lewej stronie, umieszczony centralnie nad innym Image w 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); 
0

Należy znaleźć rozwiązanie, które wykorzystuje właściwości left i top z płótna dla metody rozszerzenia.Zobacz następujący kod:

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

Ciągle mają wartości NaN lub 0 dla moich zagnieżdżonych elementów, tutaj jest to zmodyfikowana wersja odpowiedzi Danny'ego:

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); 
    } 
Powiązane problemy