Autor Beitrag
Cjreek
Hält's aus hier
Beiträge: 13

Windows 7 64-Bit
C# (VS 2013), Delphi 2010
BeitragVerfasst: Mi 09.12.15 12:56 
Hallo,

Der Titel ist leider recht lang und nicht 100%ig aussagekräftig :(
Ich lasse ein Objekt entlang einer Linie laufen indem ich Canvas.LeftProperty, Canvas.TopProperty und den Angle des RotateTransform des Objekts mithilfe einer DoubleAnimationUsingPath animiere.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
DoubleAnimationUsingPath animX = new DoubleAnimationUsingPath();
animX.PathGeometry = path;
animX.Source = PathAnimationSource.X;
animX.Duration = new Duration(TimeSpan.FromMilliseconds(1000));

DoubleAnimationUsingPath animY = new DoubleAnimationUsingPath();
animY.PathGeometry = path;
animY.Source = PathAnimationSource.Y;
animY.Duration = new Duration(TimeSpan.FromMilliseconds(1000));

DoubleAnimationUsingPath animA = new DoubleAnimationUsingPath();
animA.PathGeometry = path;
animA.Source = PathAnimationSource.Angle;
animA.Duration = new Duration(TimeSpan.FromMilliseconds(1000));

MyObject.BeginAnimation(Canvas.LeftProperty, animX);
MyObject.BeginAnimation(Canvas.TopProperty, animY);
(MyObject.RenderTransform as RotateTransform).BeginAnimation(RotateTransform.AngleProperty, animA);


Das funktioniert soweit auch sehr gut.
Was mich allerdings stört ist, dass er bei "Linkskurven" zum Beispiel nicht 20° nach links dreht, sondern 340° nach rechts.
Habe ich da irgendwie Einfluss oder gibt es irgendeine (andere) Möglichkeit das zu erreichen?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 09.12.15 13:26 
Da die Eigenschaft RotateTransform.Angle nur positive Gradmaße (0-360) zurückgibt, müßtest du ein eigenes DependencyProperty erstellen, welches bei Bedarf (d.h. > 180) negative Werte (d.h. Angel-360) zurückgibt.
Cjreek Threadstarter
Hält's aus hier
Beiträge: 13

Windows 7 64-Bit
C# (VS 2013), Delphi 2010
BeitragVerfasst: Mi 09.12.15 14:50 
Danke für die schnelle Antwort!
Ich habs probiert, aber das Problem ist, dass die Pfadanimation schon die "falschen" Werte übergibt.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
public static readonly DependencyProperty ProxyAngleProperty = DependencyProperty.RegisterAttached("ProxyAngle"typeof(double), typeof(MyClass), new PropertyMetadata(OnProxyAngleChanged));

private static void OnProxyAngleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
   Debug.Print("old: " + (double)e.OldValue + ", new: " + (double)e.NewValue);
}

MyObject.BeginAnimation(ProxyAngleProperty, animA);


Ausgangswinkel 37°. Animation einer Linkskurve protokolliert aus der dem Change-Ereignis meiner "Proxy"-Dependency Property:

Zitat:
old: 37,3180944028608, new: 127,318015032881
old: 127,318015032881, new: 243,43510380261
old: 243,43510380261, new: 333,43495508721


Ich muss dann ja aus meiner Proxy-Property den Angle der RotateTransform setzen. Aber auf was?
Mit den Werten die ich da reinbekommen sehe ich keine Möglichkeit mein Problem zu beheben.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 09.12.15 18:17 
Ich meine so etwas wie:
ausblenden C#-Quelltext
1:
var new_angle = (angle > 180)? angle - 360 : angle;					

Debugge mal, welches konkrete Objekt du für den Parameter d erhältst. Dies müßte ja vom Typ RotateTransform sein, d.h. du kannst dann so etwas benutzen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
var source = d as RotateTransform;
if (source != null)
{
   source.Angle = new_angle;
}


PS: Ich hoffe ich bin nicht völlig auf dem Holzweg (ich habe u.a. bei der Suche nach "wpf rotate counterclockwise" folgendes gefunden: Rotation Transforms).

Ansonsten fällt mir nur ein, daß du eine eigene DoubleAnimationUsingPath-Klasse für den Angle benutzt, welcher dann entsprechende Umrechnungen vornimmt.
Cjreek Threadstarter
Hält's aus hier
Beiträge: 13

Windows 7 64-Bit
C# (VS 2013), Delphi 2010
BeitragVerfasst: Mi 09.12.15 18:36 
Ja aber überleg mal wie die Animation aussieht wenn du in deinem Code für "angle" meine Beispielwerte von dem Post obendrüber einsetzt.
Im besten Fall rotiert er nach rechts von 37° nach 127° und dann ZURÜCK nach -117° (+243°) und dann wieder ein Stück nach vorne bis -27° (333°).

Das wäre also eine vor->zurück->vor-Bewegung, bzw. unterm Strich geht er den gleichen Weg wie vorher, da die Rotation ja nur nacheinander auf die oben genannten Werte gesetzt wird.
D.h. obwohl es rechnerisch vor-zurück-vor ist, sieht es immernoch nach vor-vor-vor und "falsch rum" aus.

Der kleinste Weg ist ja von 37° nach 333° gegen den Uhrzeigersinn. Alle Punkte die ich außerhalb dieses Bereichs bekomme, machen die Animation ja schon kaputt.
Verstehst du was ich meine?

Edit: Sorry ich hatte dir aus Versehn ne PN geschickt statt auf den Thread zu antworten - falscher Button :?

Moderiert von user profile iconTh69: Full-Quote entfernt.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 09.12.15 18:43 
Hatte noch ein Edit (letzte Zeile) hinzugefügt, nachdem mir aufgefallen ist, daß dies doch nicht so funktionieren kann (wie du ja auch beschrieben hast).

PS: Es wundert mich, daß es im großen Netz anscheinend keine Lösung dafür gibt (oder keiner braucht so etwas?).
Cjreek Threadstarter
Hält's aus hier
Beiträge: 13

Windows 7 64-Bit
C# (VS 2013), Delphi 2010
BeitragVerfasst: Mi 09.12.15 19:48 
Hab grad rausgefunden wo das Problem herkommt. Ich erstelle den Animations-Path durch einen String wie:

Zitat:
M 50,50 L 50,150 L 140,240 L 260,240 L 150,150


ausblenden C#-Quelltext
1:
Geometry.Parse("M 50,50 L 50,150 L 140,240 L 260,240 L 150,150")					


Geometry.Parse gibt allerdings ein StreamGeometry Objekt zurück.
Da ich für meine Animation eine PathGeometry brauche blieben mir 3 Möglichkeiten:

ausblenden C#-Quelltext
1:
2:
3:
StreamGeometry.GetWidenedPathGeometry
StreamGeometry.GetOutlinedPathGeometry
StreamGeometry.GetFlattenedPathGeometry


GetFlattenedPathGeometry schien gut zu funktionieren (auch die Kurven nimmt er korrekt!), aber das animierte Objekt schien eher "neben" dem Pfad herzulaufen dadurch dass der Ursprung natürlich in der oberen linken Ecke sitzt und nicht in der Mitte des Objekts.

Meine Lösung war GetWidenedPathGeometry, wo ich durch den übergebenen Pen eine Art Offset erzeugen konnte.
Aber bei der Animation mit den durch diese Methode erzeugten Pfade entstand das Problem was ich jetzt habe.

Ich weiß nicht ob das beobachtete Verhalten ein Bug ist oder gewollt. Ich verstehe es zumindest nicht.
Vielleicht gibt es ja auch eine Alternative zu GetWidenedPathGeometry um zu verhindern dass das Objekt "neben" dem Pfad herläuft?