DoubleAnimation reverse 2x faster - c#

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);

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)
});

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!

immediate translate animation in WPF in code behind

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.

Simultaneous Animation For Same Element in WPF

I have an image in a canvas. What I want to do is code an animation which both rotates the image 90 degrees and move the image from the top left corner of canvas to the bottom right corner at the same time to create an action looks like projectile motion. However, I could only manage to do one part of the animation so far.
DoubleAnimation rotateAnimation = new DoubleAnimation(0, 90, new Duration(TimeSpan.FromSeconds(1)));
RotateTransform rt = new RotateTransform();
image.RenderTransform = rt;
rt.BeginAnimation(RotateTransform.AngleProperty, rotateAnimation);
TranslateTransform tt = new TranslateTransform();
image.RenderTransform = tt;
DoubleAnimation moveXAnimation = new DoubleAnimation(0, 300, TimeSpan.FromSeconds(1));
DoubleAnimation moveYAnimation = new DoubleAnimation(0, 300, TimeSpan.FromSeconds(1));
tt.BeginAnimation(TranslateTransform.XProperty, moveXAnimation);
tt.BeginAnimation(TranslateTransform.YProperty, moveYAnimation);
These two blocks works very well separately, but do not work together(consequently). The latter one works only. Anyone can tell me why?
UPDATE (Complete answer of Clemens):
RotateTransform rt = new RotateTransform();
DoubleAnimation rotateAnimation = new DoubleAnimation(0, 90, new Duration(TimeSpan.FromSeconds(5)));
TranslateTransform tt = new TranslateTransform();
DoubleAnimation moveXAnimation = new DoubleAnimation(0, 300, TimeSpan.FromSeconds(5));
DoubleAnimation moveYAnimation = new DoubleAnimation(0, 300, TimeSpan.FromSeconds(5));
TransformGroup transform = new TransformGroup();
transform.Children.Add(rt);
transform.Children.Add(tt);
image.RenderTransformOrigin = new Point(0.5, 0.5);
image.RenderTransform = transform;
rt.BeginAnimation(RotateTransform.AngleProperty, rotateAnimation);
tt.BeginAnimation(TranslateTransform.XProperty, moveXAnimation);
tt.BeginAnimation(TranslateTransform.YProperty, moveYAnimation);
Put both transforms in a TransformGroup, and assign that to the image's RenderTransform:
var rt = new RotateTransform();
var tt = new TranslateTransform();
var transform = new TransformGroup();
transform.Children.Add(rt);
transform.Children.Add(tt);
image.RenderTransform = transform;
// run animations
You may also want to take a look at how to use a Path Animation for a more realistic look. The projectile might follow a parabolic curve.

Applying animated ScaleTransform in code problem

I am trying to find out why the code below does not seem to work. It does not give an error - it simply doesn't scale. It actually does seem to work if I change it as to my second code sample.
Anyone got any idea?
Thanks
public static void StartMouseEnterAnimation(Button button)
{
Storyboard storyboard = new Storyboard();
ScaleTransform scale = new ScaleTransform(1.0, 1.0, 1, 1);
button.RenderTransformOrigin = new Point(0.5, 0.5);
button.RenderTransform = scale;
DoubleAnimation growAnimation = new DoubleAnimation();
growAnimation.Duration = TimeSpan.FromMilliseconds(300);
growAnimation.From = 1;
growAnimation.To = 1.8;
storyboard.Children.Add(growAnimation);
Storyboard.SetTargetProperty(growAnimation, new PropertyPath(ScaleTransform.ScaleXProperty));
Storyboard.SetTarget(growAnimation, scale);
storyboard.Begin();
}
--- The following DOES work but I had to create a TransformGroup and reference this through a more complicated PropertyChain...
public static void StartMouseEnterAnimation(Button button)
{
Storyboard storyboard = new Storyboard();
ScaleTransform scale = new ScaleTransform(1.0, 1.0, 1, 1);
button.RenderTransformOrigin = new Point(0.5, 0.5);
TransformGroup myTransGroup = new TransformGroup();
myTransGroup.Children.Add(scale);
button.RenderTransform = myTransGroup;
DoubleAnimation growAnimation = new DoubleAnimation();
growAnimation.Duration = TimeSpan.FromMilliseconds(100);
//growAnimation.From = 1;
growAnimation.To = 1.1;
storyboard.Children.Add(growAnimation);
DependencyProperty[] propertyChain = new DependencyProperty[]
{
Button.RenderTransformProperty,
TransformGroup.ChildrenProperty,
ScaleTransform.ScaleXProperty
};
string thePath = "(0).(1)[0].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(growAnimation, myPropertyPath);
Storyboard.SetTarget(growAnimation, button);
storyboard.Begin();
}
I was able to get it to work by tweaking your first code sample like so:
public static void StartMouseEnterAnimation(Button button) {
Storyboard storyboard = new Storyboard();
ScaleTransform scale = new ScaleTransform(1.0, 1.0);
button.RenderTransformOrigin = new Point(0.5, 0.5);
button.RenderTransform = scale;
DoubleAnimation growAnimation = new DoubleAnimation();
growAnimation.Duration = TimeSpan.FromMilliseconds(300);
growAnimation.From = 1;
growAnimation.To = 1.8;
storyboard.Children.Add(growAnimation);
Storyboard.SetTargetProperty(growAnimation, new PropertyPath("RenderTransform.ScaleX"));
Storyboard.SetTarget(growAnimation, button);
storyboard.Begin();
}
Instead of new PropertyPath(ScaleTransform.ScaleXProperty)), I used new PropertyPath("RenderTransform.ScaleX")), and I set the target of the storyboard to the button (not the scaleTransform itself).
Hope that helps!
Here is an example of how to animate in two different directions on a ScaleTransform, when you have a transform group. The path string shows which part is being animated. Also, because Canvas is freezable, you have to RegisterName. (I don't know what this means, but it is required)
var storyBoard = new Storyboard();
var group = new TransformGroup();
var scale = new ScaleTransform(Zoom, Zoom);
group.Children.Add(scale);
group.Children.Add(new TranslateTransform(_translateX,_translateY));
MainCanvas.RenderTransform = group;
RegisterName("MainCanvas",MainCanvas);
var growAnimation = new DoubleAnimation();
growAnimation.Duration = TimeSpan.FromMilliseconds(1000);
growAnimation.From = _oldZoom;
growAnimation.To = Zoom;
storyBoard.Children.Add(growAnimation);
var growAnimation2 = new DoubleAnimation();
growAnimation2.Duration = TimeSpan.FromMilliseconds(1000);
growAnimation2.From = _oldZoom;
growAnimation2.To = Zoom;
storyBoard.Children.Add(growAnimation2);
string thePath = "(0).(1)[0].(2)"; // Not used - just to show the syntax
Storyboard.SetTargetProperty(growAnimation, new PropertyPath("RenderTransform.Children[0].ScaleX"));
Storyboard.SetTargetProperty(growAnimation2, new PropertyPath("RenderTransform.Children[0].ScaleY"));
Storyboard.SetTargetName(growAnimation, "MainCanvas");
Storyboard.SetTargetName(growAnimation2,"MainCanvas");
storyBoard.Begin(this);

Categories