immediate translate animation in WPF in code behind - c#

I want to make an animation that involves translating a circle _fixedCircle on x-axis from starting point (5,0) to end point (200,0) and then from (200,0) to (5,0) In a forever loop but not following a path, but "jumping", in other words, immediate translation from point to point.
To animate this circle doing a linear interpolation there is this:
Storyboard sb = new Storyboard();
DoubleAnimation anim = new DoubleAnimation();
sb.Children.Add(anim);
Storyboard.SetTarget(anim, _fixedCircle);
Storyboard.SetTargetProperty(anim, new PropertyPath("(Canvas.Left)"));
anim.From = 5;
anim.To = 200;
anim.RepeatBehavior = RepeatBehavior.Forever;
anim.AutoReverse = true;
MYCANVAS.Resources.Add("CIRCLE_ID", sb);
Duration duration = new Duration(TimeSpan.FromSeconds(2));
anim.Duration = duration;
anim.Begin();
But how to create "jumping" effect?

Try using a DoubleAnimationUsingKeyFrames, adding a DiscreteDoubleKeyFrame for each jump you want, e.g. (calculation of jump values has a lot of room for improvement ;)):
DoubleAnimationUsingKeyFrames anim = new DoubleAnimationUsingKeyFrames();
int maxNrOfJumps = 10;
for (int jump = 0; jump < maxNrOfJumps; jump++) {
double value = ((200 - 5) / maxNrOfJumps) * jump;
anim.KeyFrames.Add(new DiscreteDoubleKeyFrame(value, KeyTime.FromPercent(jump / (double)maxNrOfJumps)));
}
Discrete key frames like DiscreteDoubleKeyFrame create sudden "jumps" between values (no Interpolation). In other words, the animated property does not change until the key frame's key time is reached at which point the animated property goes suddenly to the target value.
https://msdn.microsoft.com/en-us/library/system.windows.media.animation.discretedoublekeyframe%28v=vs.110%29.aspx
Edit:
Running it can be done without a Storyboard, this is how I tested it:
_fixedCircle.BeginAnimation(Canvas.LeftProperty, anim);
Edit2:
You'd still need to set these properties to keep the animation running:
anim.RepeatBehavior = RepeatBehavior.Forever;
anim.AutoReverse = true;
Also, don't forget to set the Duration...

immediate translation from point to point
Are you looking for a kind of instant teleportation from the first point to the last one ?
If so :
Storyboard sb = new Storyboard();
DoubleAnimation anim = new DoubleAnimation();
sb.Children.Add(anim);
Storyboard.SetTarget(anim, _fixedCircle);
Storyboard.SetTargetProperty(anim, new PropertyPath("(Canvas.Left)"));
anim.From = 5;
anim.To = 200;
// anim.RepeatBehavior = RepeatBehavior.Forever; // nope
anim.AutoReverse = false; // well
MYCANVAS.Resources.Add("CIRCLE_ID", sb);
Duration duration = new Duration(TimeSpan.FromSeconds(0)); // here we go
anim.Duration = duration;
anim.Begin();

Why not use skipToFill property?
just add it to your storyboard.

Related

WPF. Animation of window transparency

I need a smooth animation of window transparency. I added this code to the "LOADED" event of the window.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 100.0;
myDoubleAnimation.To = 0.1;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(UIElement.OpacityProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
myStoryboard.Begin(this);
There is a sharp jump of transparency. Animation is missing. Where there has been a mistake?
Opacity is a relative value in the range 0 .. 1. Use
myDoubleAnimation.From = 1.0;
or don't set it at all.
Instead of using a Storyboard, you may also just write
BeginAnimation(OpacityProperty, new DoubleAnimation
{
To = 0.1,
Duration = TimeSpan.FromSeconds(1)
});

Specifying PropertyPath for a MapIcon Latitude value in UWP Bing Maps

I am trying to animate the location of a MapIcon in the UWP version of Bing Maps. I am having problems specifying the PropertyPath for the Latitude component (a double value) of the GeoPoint used as the center value for the icon:
MapIcon mapIcon1 = new MapIcon();
mapIcon1.Location = myMap.Center;
mapIcon1.NormalizedAnchorPoint = new Point(0.5, 1.0);
mapIcon1.Title = "My Friend";
mapIcon1.Image = mapIconStreamReference;
mapIcon1.ZIndex = 0;
myMap.MapElements.Add(mapIcon1);
double centerLatitude = myMap.Center.Position.Latitude;
double centerLongitude = myMap.Center.Position.Longitude;
Storyboard storyboard = new Storyboard();
DoubleAnimation animation = new DoubleAnimation();
animation.From = centerLatitude;
animation.To = centerLatitude + 100f;
animation.Duration = new Duration(new TimeSpan(0, 0, 0, 5));
animation.EnableDependentAnimation = true;
storyboard.Children.Add(animation);
//Storyboard.SetTargetProperty(animation, "(MapIcon.Location)(Geopoint.Position)(BasicGeoposition.Latitude)");
//Storyboard.SetTargetProperty(animation, "(MapIcon.Location)(MapControl.Center)(Geopoint.Position)(BasicGeoposition.Latitude)");
//Storyboard.SetTargetProperty(animation, "(MapIcon.Location)(BasicGeoposition.Latitude)");
//Storyboard.SetTargetProperty(animation, "(MapIcon.Location.Latitude)");
Storyboard.SetTarget(storyboard, mapIcon1);
storyboard.Begin();
None of the commented out statements work; they all result in the "Cannot resolve TargetProperty on specified object" error. I was particularly hopeful for the first attempt "(MapIcon.Location)(Geopoint.Position)(BasicGeoposition.Latitude)", but no luck.
(I am able to animate the Color attribute of a MapIcon successfully.)
Storyboard.SetTargetProperty targets the dependency property where the animation applies. So, what you want to apply animation to 'Latitude'is impossible.
You would have to make it by yourself. For example, using the DispatcherTimer.

How to move an image pixel by pixel?

So I have 2 Image's I want the first Image to move towards the other Image I have both X,Y coordinates, how should this be done if I want it moving pixel by pixel towards the target Image?
Bare in mind, I'm using Windows-Universal I've tried DoubleAnimation but my knowledge in that stuff is really bad, I don't know where to start. The Image would sometimes have to move diagonally (across) rather than moving right then up.
How should I do this?
This is what I have so far:
private void MoveToTarget_Start()
{
moveToTimer = new DispatcherTimer();
moveToTimer.Tick += MoveToTarget_Tick;
moveToTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
moveToTimer.Start();
}
void MoveToTarget_Tick(object sender, object e)
{
}
First, you need to know how many pixels you need to move. For that, we can try to retrieve the absolute position of each element and compare them (there may be a more straightforward way, I just don't know how):
private Point GetAbsolutePosition(UIElement element)
{
var ttv = element.TransformToVisual(Window.Current.Content);
return ttv.TransformPoint(new Point(0, 0));
}
(taken from this answer)
From there, we retrieve the point of each element and compute the difference:
var position1 = GetAbsolutePosition(Image1);
var position2 = GetAbsolutePosition(Image2);
var offsetX = position2.X - position1.X;
var offsetY = position2.Y - position1.Y;
Now, we now of how many pixels we'll have to move on each axis. We add the TranslateTransform for the element (it may be better to do that beforehand directly from the XAML):
var translateTransform = new TranslateTransform();
image1.RenderTransform = translateTransform;
Finally, we create the animations, and target the TranslateTransform. Then we group them in a Storyboard, and start it:
var animationX = new DoubleAnimation()
{
From = 0,
To = offsetX,
Duration = TimeSpan.FromSeconds(2)
};
var animationY = new DoubleAnimation()
{
From = 0,
To = offsetY,
Duration = TimeSpan.FromSeconds(2)
};
Storyboard.SetTarget(animationX, translateTransform);
Storyboard.SetTargetProperty(animationX, "X");
Storyboard.SetTarget(animationY, translateTransform);
Storyboard.SetTargetProperty(animationY, "Y");
var storyboard = new Storyboard();
storyboard.Children.Add(animationX);
storyboard.Children.Add(animationY);
storyboard.Begin();
To be honest the best idea is to use DoubleAnimation and Storyboard classes.
I would set background as Canvas then You can animate it throught Canvas.SetLeft and Canvas.SetTop properties.
First You should create DoubleAnimationC class
DoubleAnimation da = new DoubleAnimation()
{
SpeedRatio = 3.0,
AutoReverse = false,
From = 0
To = 100
BeginTime = TimeSpan.FromSeconds(x),
};
Storyboard.SetTarget((Timeline)doubleAnimation, YOUR IMAGE);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Top)"));
Of course change those properties as You like and now we must create StoryBoard class which will contains our animation
Storyboard sb = new Storyboard();
sb.Children.Add(da);
sb.Start();
Hope it helps!

DoubleAnimation reverse 2x faster

I have a DoubleAnimation set for a DropShadowEffect to change Blur Radius up and down producing a glowing animated shadow like this:
DropShadowEffect DS = new DropShadowEffect();
/// Whatever DS settings here
Target.Effect = DS;
DoubleAnimation DSr = new DoubleAnimation(0, 25, new Duration(TimeSpan.FromMilliseconds(500)));
DSr.AutoReverse = true;
DSr.RepeatBehavior = RepeatBehavior.Forever;
DS.BeginAnimation(DropShadowEffect.BlurRadiusProperty, DSr);
It takes 20 milliseconds to make one step forward, and total time of 500 milliseconds.
Is it possible to make the reverse action step back once every 10 milliseconds with total time of 250 milliseconds (two times normal speed).
Well i figured i can use Completed event to do something like this:
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0);
animation.Duration = TimeSpan.FromMilliseconds(500);
animation.Completed += (s, e) =>
{
If (target.opacity == 1)
{
animation.From = 1.0;
animation.To = 0.0;
animation.Duration = TimeSpan.FromMilliseconds(250);
element.BeginAnimation(OpacityProperty, animation);
}
else
{
animation.From = 0.0;
animation.To = 1.0;
animation.SpeedRatio = TimeSpan.FromMilliseconds(500);
element.BeginAnimation(OpacityProperty, animation);
}
}
element.BeginAnimation(OpacityProperty, animation);

Wpf animations from code

There was some similar threads, but I didn't find solution of my problem. It's my first post here.
Here's the thing:
Viewport3D viewPort3D;
GeometryModel3D geometryModel = new GeometryModel3D();
Transform3DGroup transform3DGroup = new Transform3DGroup();
...
// Rotation
RotateTransform3D rotateTransform3D = new RotateTransform3D();
AxisAngleRotation3D axisAngleRotation3d = new AxisAngleRotation3D();
axisAngleRotation3d.Axis = new Vector3D(0, 1, 0);
axisAngleRotation3d.Angle = angle;
rotateTransform3D.Rotation = axisAngleRotation3d;
transform3DGroup.Children.Add(rotateTransform3D);
// Translation
TranslateTransform3D translateTransform3D = new TranslateTransform3D();
translateTransform3D.OffsetX = offsetX;
transform3DGroup.Children.Add(translateTransform3D);
// Adding transforms
geometryModel.Transform = transform3DGroup;
Model3DGroup model3DGroup = new Model3DGroup();
model3DGroup.Children.Add( image.getGeometryModel3D() );
modelVisual3D.Content = model3DGroup;
viewPort3D.Children.Add( modelVisual3D );
And now I want to make translation using storyboard (because later I want to add also rotating to that storyboard):
Storyboard s = new Storyboard();
Transform3DGroup transform3DGroup = model3DGroup.Children.ElementAt(current).Transform as Transform3DGroup;
for (int j = 0; j < transform3DGroup.Children.Count; ++j)
{
if (transform3DGroup.Children.ElementAt(j) is TranslateTransform3D)
{
TranslateTransform3D translation = transform3DGroup.Children.ElementAt(j) as TranslateTransform3D;
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = 0;
doubleAnimation.To = 2;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
doubleAnimation.AutoReverse = true;
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
s.Children.Add(doubleAnimation);
s.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(doubleAnimation, model3DGroup.Children.ElementAt(current));
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Model3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)"));
s.Begin(); // Exception during the execution.
}
}
Exception in the last line:
'[Unknown]' property value in the path
'(Model3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)'
points to immutable instance of
'System.Windows.Media.Media3D.TranslateTransform3D'.
I took PropertyPath similar to the path generated in blend 4.
Thank you for any help.
I think because translate tranform 3d is an immutable instance it has to be indicated that it should be mutable while rendering / translation is taking place.
I guess
We can supply x:Name to that immutable TranslateTransform3D object, to make it mutable.
Bind to its property than to animate it.
E.g. in your case
NameScope.SetNameScope(this, new NameScope());
this.RegisterName("AxisRotation", MyAxisRotation3DObject.Rotation);
this.RegisterName("TranslateTransformation", MyTranslation3DObject);
This way we give names to Axis Rotation 3D and Translate Transform 3D objects and then in double animations refer them as Storyboard.SetTargetName(.., "AxisRotation") and Storyboard.SetTargetName(.., "TranslateTransformation") and access their direct properties such as Storyboard.SetTargetProperty(.., new PropertyPath("Angle")) and Storyboard.SetTargetProperty(.., new PropertyPath("OffsetX")) resp.
Your error states that TranslateTransform3D is immutable, what means, it cannot be changed. And you're trying to animate one of its properties, hence got the error.

Categories