I have popup and i have a animation using its horizontal and vertical offsets. This Animation takes these offsets as values and have a simple storyboard. For the 1st time it works fine and the second time, the Horizontal offset was not updating the value. I dono why its like this. I have checked the Dp with the property changed handlers, its not get changed. Retains its old value. There is no binding at all, value is set directly.
What might be the reason for this. Any idea on this??
var duration = new TimeSpan(0, 0, 0, 0, 200);
horizontalDoubleAnimation = new EasingDoubleKeyFrame();
verticalDoubleAnimation = new EasingDoubleKeyFrame();
horizontalDoubleAnimation.KeyTime = KeyTime.FromTimeSpan(duration);
verticalDoubleAnimation.KeyTime = KeyTime.FromTimeSpan(duration);
horizontalDoubleAnimation.EasingFunction = new CircleEase();
verticalDoubleAnimation.EasingFunction = new CircleEase();
DoubleAnimationUsingKeyFrames horizontalAnimationUsingKeyFrames = new DoubleAnimationUsingKeyFrames();
DoubleAnimationUsingKeyFrames verticalAnimationUsingKeyFrames = new DoubleAnimationUsingKeyFrames();
horizontalAnimationUsingKeyFrames.KeyFrames.Add(horizontalDoubleAnimation);
verticalAnimationUsingKeyFrames.KeyFrames.Add(verticalDoubleAnimation);
reverseAnimationStoryboard = new Storyboard { Duration = duration };
reverseAnimationStoryboard.Children.Add(horizontalAnimationUsingKeyFrames);
reverseAnimationStoryboard.Children.Add(verticalAnimationUsingKeyFrames);
Storyboard.SetTarget(horizontalAnimationUsingKeyFrames, this.DraggablePopup);
Storyboard.SetTarget(verticalAnimationUsingKeyFrames, this.DraggablePopup);
Storyboard.SetTargetProperty(horizontalAnimationUsingKeyFrames, new PropertyPath("HorizontalOffset"));
Storyboard.SetTargetProperty(verticalAnimationUsingKeyFrames, new PropertyPath("VerticalOffset"));
this.DraggablePopup.Resources.Add("storyboard", reverseAnimationStoryboard);
Related
I created an animation of Dependency Property Canvas.Left with code:
DoubleAnimation myDoubleAnimation = new DoubleAnimation { From =1, To = 100, Duration = new Duration(TimeSpan.FromMilliseconds(500)) };
Storyboard.SetTarget(myDoubleAnimation, Image);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath("(Canvas.Left)"));
Storyboard myMovementStoryboard = new Storyboard();
myMovementStoryboard.Children.Add(myDoubleAnimation);
myMovementStoryboard.Begin();
After the animation, I need to clear it with
UIElement.BeginAnimation(DependencyProperty, AnimationTimeline)
by a null AnimationTimeline.
Otherwise, the Canvas.Left will never change after I modify it by code.
However, the UIElement.BeginAnimation only accepts DependencyProperty but not a PropertyPath.
How can I solve this? Thank you.
You would call
Image.BeginAnimation(Canvas.LeftProperty, null);
The Storyboard is redundant. You could as well call
Image.BeginAnimation(Canvas.LeftProperty, myDoubleAnimation);
You may also avoid that the animation holds the value by setting
myDoubleAnimation = new DoubleAnimation
{
From = 1,
To = 100,
Duration = TimeSpan.FromMilliseconds(500),
FillBehavior = FillBehavior.Stop
};
I am making a sidebar-style app which is located on the left of right side of the screen.
I am trying to make it look like it's sliding in and out of the screen, but when it's on the right, it slides in from the left still.
I can't find any right to left options regarding window width, so I was hoping to find the answer here.
Here is my current working animation code for left to right:
public static void AnimateSize(this Window target, double newWidth, EventHandler completed)
{
var length = new TimeSpan(0, 0, 0, 0, Settings.Default.AnimationTime);
var sb = new Storyboard {Duration = new Duration(length)};
var aniWidth = new DoubleAnimationUsingKeyFrames();
aniWidth.Duration = new Duration(length);
aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(target.ActualWidth,
KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, 00))));
aniWidth.KeyFrames.Add(new EasingDoubleKeyFrame(newWidth, KeyTime.FromTimeSpan(length)));
Storyboard.SetTarget(aniWidth, target);
Storyboard.SetTargetProperty(aniWidth, new PropertyPath(FrameworkElement.WidthProperty));
sb.Children.Add(aniWidth);
sb.Completed += completed;
sb.Begin();
}
called like this:
_window.AnimateSize(0, delegate { _window.Hide(); });
and this:
_window.Width = 0;
_window.Show();
_window.AnimateSize(Settings.Default.Width, delegate { });
Thanks.
private void Animate(double beginfrom, double to, DependencyProperty dp)
{
var da = new DoubleAnimation {
From = beginfrom,
To = to,
FillBehavior = FillBehavior.Stop,
Duration = new Duration(TimeSpan.FromSeconds(0.3)),
AccelerationRatio = 0.1
};
var storyBoard = new Storyboard();
storyBoard.Children.Add(da);
Storyboard.SetTarget(da, this); //this = your control object
Storyboard.SetTargetProperty(da, new PropertyPath(dp));
storyBoard.Begin();
}
Simple usage: Animate(0, 250, WidthProperty);
I had similar task to accomplish. I used to animate the left property of my window and make it appear as though it slides from the outside and disappears in the same fashion. but when a colleague who uses two screens used it , the window would slide onto the other screen.
The work around used was to simultaneously animate the width and left properties. this gives the effect of the window appearing at the desired location and unfurling towards the left.
DoubleAnimation daLeftAppear = new DoubleAnimation(popupWidthDetails.workAreaWidth, (<workAreaWidth> - <windowWidth> - 5), new Duration(TimeSpan.FromSeconds(1)));
daLeftAppear.EasingFunction = new QuarticEase();
Storyboard.SetTargetName(daLeftAppear, this.Name);
Storyboard.SetTargetProperty(daLeftAppear, new PropertyPath(LeftProperty));
DoubleAnimation daWidthAppear = new DoubleAnimation(0, 100, new Duration(TimeSpan.FromSeconds(1)));
daWidthAppear.EasingFunction = new QuarticEase();
Storyboard.SetTargetName(daWidthAppear, this.Name);
Storyboard.SetTargetProperty(daWidthAppear, new PropertyPath(WidthProperty));
sbAppear = new Storyboard();
sbAppear.Children.Add(daLeftAppear);
sbAppear.Children.Add(daWidthAppear);
I want to apply a Blink animation to a Canvas so that all the objects I have drawn on it would blink with it.
I have been somewhat successful using the code below which changes the Opacity property of the Canvas rather fast to achieve this effect but I'm kinda not satisfied with it.
I would prefer a pure blink without any FadeOut/FadeIn as in my current code. How can I do it the right way?
var blinkAnimation = new DoubleAnimation
{
From = 1,
To = 0
};
var blinkStoryboard = new Storyboard
{
Duration = TimeSpan.FromMilliseconds(500),
RepeatBehavior = RepeatBehavior.Forever,
AutoReverse = true
};
Storyboard.SetTarget(blinkAnimation, MyCanvas);
Storyboard.SetTargetProperty(blinkAnimation, new PropertyPath(OpacityProperty));
blinkStoryboard.Children.Add(blinkAnimation);
MyCanvas.BeginStoryboard(blinkStoryboard);
Maybe I can do that using the VisibilityProperty but I couldn't get it right.
You might use a second animation with an appropriate BeginTime:
var switchOffAnimation = new DoubleAnimation
{
To = 0,
Duration = TimeSpan.Zero
};
var switchOnAnimation = new DoubleAnimation
{
To = 1,
Duration = TimeSpan.Zero,
BeginTime = TimeSpan.FromSeconds(0.5)
};
var blinkStoryboard = new Storyboard
{
Duration = TimeSpan.FromSeconds(1),
RepeatBehavior = RepeatBehavior.Forever
};
Storyboard.SetTarget(switchOffAnimation, MyCanvas);
Storyboard.SetTargetProperty(switchOffAnimation, new PropertyPath(Canvas.OpacityProperty));
blinkStoryboard.Children.Add(switchOffAnimation);
Storyboard.SetTarget(switchOnAnimation, MyCanvas);
Storyboard.SetTargetProperty(switchOnAnimation, new PropertyPath(Canvas.OpacityProperty));
blinkStoryboard.Children.Add(switchOnAnimation);
MyCanvas.BeginStoryboard(blinkStoryboard);
If you want on/off state for your animation you can change your animation to DoubleAnimationUsingKeyFrames
var blinkAnimation = new DoubleAnimationUsingKeyFrames();
blinkAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))));
blinkAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(250))));
var blinkStoryboard = new Storyboard
{
Duration = TimeSpan.FromMilliseconds(500),
RepeatBehavior = RepeatBehavior.Forever,
};
Storyboard.SetTarget(blinkAnimation, MyCanvas);
Storyboard.SetTargetProperty(blinkAnimation, new PropertyPath(OpacityProperty));
blinkStoryboard.Children.Add(blinkAnimation);
blinkStoryboard.Begin();
This may be animation related. I have a WPF control whose width and height I'm animating through several different storyboards. I create the storyboards and then call Begin() on them. I've provided code for how the storyboards look below.
I want to re-evaluate the control size on some event (e.g. window resize) so that it is different from the value that was animated. I attempt to handle this on SizeChanged manually (after the animation has run) by setting the Width and Height properties of my control. The debugger shows that those values are not set (the original values remain).
When I inspect the WPF through Snoop, the Width and Height rows are highlighted in a peach/orange color and trying to set the values through it again does not persist it (the original value is shown when I focus away. My guess is that my animation is somehow overriding manual changes to the property but I'm not sure if this is true or how to solve it.
Storyboard Class
public class MyAnimationClass
{
private Storyboard _myStoryboard;
private DoubleAnimation _animation1;
private DoubleAnimation _animation2;
private DoubleAnimation _animation3;
private void InitializeStoryboard()
{
_myStoryboard = CreateMyStoryboard(out _animation1, out _animation2, out _animation3);
}
private Storyboard CreateMyStoryboard(out DoubleAnimation animation1, out DoubleAnimation animation2, out DoubleAnimation animation3)
{
var myStoryboard = new Storyboard();
// create animations
animation1 = new DoubleAnimation { Duration = new TimeSpan(0, 0, 0, 0, 250), From = 0, To = 0 };
animation2 = new DoubleAnimation { BeginTime = new TimeSpan(), Duration = new TimeSpan(0, 0, 0, 0, 250), From = 35, To = 35 };
animation3 = new DoubleAnimation { BeginTime = new TimeSpan(0, 0, 0, 0, 250), Duration = new TimeSpan(0, 0, 0, 0, 250), From = 35, To = 0 };
Storyboard.SetTargetProperty(animation1, new PropertyPath(FrameworkElement.WidthProperty));
Storyboard.SetTargetProperty(animation2, new PropertyPath(FrameworkElement.HeightProperty));
Storyboard.SetTargetProperty(animation3, new PropertyPath(FrameworkElement.HeightProperty));
myStoryboard.Children.Add(animation1);
myStoryboard.Children.Add(animation2);
myStoryboard.Children.Add(animation3);
return myStoryboard;
}
public void Animate(Control controlToAnimate)
{
// ....
var finalWidth = CalculateFinalWidth();
var finalHeight = CalculateFinalHeight();
_animation1.To = finalWidth;
_animation3.To = finalHeight;
_myStoryboard.Begin(controlToAnimate);
}
}
When I want to animate something, I call Animate() on the instance of my MyAnimationClass class.
Thoughts?
This ended up being a pretty simple fix. The value wasn't changing because of FillBehavior controlling the property value. However, simply changing it to FillBehavior.Stop didn't solve my problem because when my non-animation code set width/height, the next time my animation ran it would animate to the width/height I wanted and then default back to the set height. This was solved by setting the width/height of the control after calculation and before animation:
public void Animate(Control controlToAnimate)
{
// ....
var finalWidth = CalculateFinalWidth();
var finalHeight = CalculateFinalHeight();
// set values here so after animation they stay
controlToAnimate.Width = finalWidth;
controlToAnimate.Height = finalHeight;
_animation1.To = finalWidth;
_animation3.To = finalHeight;
_myStoryboard.Begin(controlToAnimate);
}
Animations in WPF provide the boolean parameter AutoReverse. Is it possible to make a call to the functionality implemented by AutoReverse = "true"?
My goal is to spare some troublesome reverse animation and especially spare alot of code. The reverse must not happen directly after the animation ended.
Example of using AutoReverse and True to animate only the reverse animation, but this does not work as required - it still animates the actual animation and the reverse animation.
TranslateTransform transform = new TranslateTransform(0.0, 0.0);
myBox.RenderTransform = transform;
sb = new Storyboard();
Duration dur = new Duration(TimeSpan.FromSeconds(0.5));
DoubleAnimation shiftAnimation = new DoubleAnimation(100.0, dur);
shiftAnimation.AutoReverse = true;
sb.Children.Add(shiftAnimation);
Storyboard.SetTarget(shiftAnimation, myBox);
Storyboard.SetTargetProperty(shiftAnimation, new PropertyPath("RenderTransform.X"));
sb.Seek(TimeSpan.FromSeconds(0.5));
sb.Begin();
you could set the timeclock to 100% of the animationduration so when the animation starts, it will skip the non-reversed part!
Edit:
if Duration is set to 0:0:1.5 you apply a new timeline to your animation set to 0:0:1.5. Autoreverse has to be set to on and then you yust have to start the animation.
Edit 2:
TranslateTransform transform = new TranslateTransform(0.0, 0.0);
myBox.RenderTransform = transform;
sb = new Storyboard();
Duration dur = new Duration(TimeSpan.FromSeconds(0.5));
DoubleAnimation shiftAnimation = new DoubleAnimation(100.0, dur);
shiftAnimation.AutoReverse = true;
sb.Children.Add(shiftAnimation);
Storyboard.SetTarget(shiftAnimation, myBox);
Storyboard.SetTargetProperty(shiftAnimation, new PropertyPath("RenderTransform.X"));
sb.Begin();
sb.Pause();
sb.Seek(sb.Duration.TimeSpan);
sb.Resume();
I have found that the following code works nicely:
private bool reverse=false;
TimeSpan animationDuration = TimeSpan.FromMilliseconds(500);
Storyboard storyboard1 = new Storyboard();
private void prepareStoryBoard(Button btn)
{
btn.RenderTransform = new CompositeTransform();
DoubleAnimation animationShrink = new DoubleAnimation() { To = 0,
Duration =animationDuration , FillBehavior = FillBehavior.HoldEnd };
storyboard1.Children.Add(animationShrink);
Storyboard.SetTarget(animationShrink, btn);
Storyboard.SetTargetProperty(animationShrink,
"(Button.RenderTransform).(CompositeTransform.ScaleX)");
}
private void toggleAnimate()
{
if(reverse==false)
{
storyboard1.AutoReverse = false;
storyboard1.Begin();
reverse=true;
}
else
{
storyboard1.AutoReverse = true;
storyboard1.Seek(animationDuration);
storyboard1.Resume();
reverse = false;
}
}
The first time toggleAnimate() is called, the animation is executed in the normal direction, the second time toggleAnimate() is invoked the animation is reversed.