I am having trouble adding multiple effects within an animation sequence in WPF. I have multiple rectangles arranged within a grid and the way the animation effect is to work is in the following order:
By default, the user sees the grid such that every cell is bounded by a silver border on a black canvas, the color of the rectangle within each cell could be transparent/black.
On mouse hover, the rectangle in the cell changes its stroke and fill to green.
On exiting the mouse over, the previous cell slowly changes color to its default state before the mouse hover.
I was able to do the animation effect for just the stroke color but not combine it with the fill properties. Here is the code snippet for creating the rectangles within the grid:
Style cellStyle = PrepareAnimationStyle();
foreach (string label in rowHeaders)
{
for (int n = 0; n < numOfCols; n++)
grid.Children.Add(new Rectangle()
{
Stroke = Brushes.Silver,
StrokeThickness = 2,
Fill = Brushes.Transparent,
Height = cellSize,
Width = cellSize,
Style = cellstyle
});
}
And here is the code that sets the animation (still in progress, can't make it work as required):
Style PrepareAnimationStyle()
{
Trigger animTrigger = new Trigger();
animTrigger.Property = ContentElement.IsMouseOverProperty;
animTrigger.Value = true;
System.Windows.Media.Animation.ColorAnimation toGreen = new System.Windows.Media.Animation.ColorAnimation((Color)ColorConverter.ConvertFromString("#FF66CC00"), TimeSpan.FromSeconds(0));
toGreen.FillBehavior = FillBehavior.HoldEnd;
System.Windows.Media.Animation.ColorAnimation toTransparent = new System.Windows.Media.Animation.ColorAnimation(Colors.Transparent, TimeSpan.FromSeconds(1));
System.Windows.Media.Animation.ColorAnimation toSilver = new System.Windows.Media.Animation.ColorAnimation(Colors.Silver, TimeSpan.FromSeconds(1));
System.Windows.Media.Animation.Storyboard sbEnter = new System.Windows.Media.Animation.Storyboard();
//Storyboard.SetTargetProperty(toGreen, new PropertyPath("Stroke.Color"));
Storyboard.SetTargetProperty(toGreen, new PropertyPath("(Shape.Fill).(SolidColorBrush.Color)"));
sbEnter.Children.Add(toGreen);
/*Storyboard sbFill = new Storyboard();
Storyboard.SetTargetProperty(toGreen, new PropertyPath("Fill.Color"));
sbFill.Children.Add(toSilver);
Storyboard sbFillEmpty = new Storyboard();
Storyboard.SetTargetProperty(toTransparent, new PropertyPath("Fill.Color"));
sbFillEmpty.Children.Add(toSilver);*/
Storyboard sbExit = new Storyboard();
//Storyboard.SetTargetProperty(toSilver, new PropertyPath("Stroke.Color"));
Storyboard.SetTargetProperty(toTransparent, new PropertyPath("Fill.Color"));
sbExit.Children.Add(toSilver);
animTrigger.EnterActions.Add(new BeginStoryboard() { Storyboard = sbEnter });
//animTrigger.EnterActions.Add(new BeginStoryboard() { Storyboard = sbFill });
//animTrigger.EnterActions.Add(new BeginStoryboard() { Storyboard = sbFillEmpty });
animTrigger.ExitActions.Add(new BeginStoryboard() { Storyboard = sbExit });
Style cellStyle = new Style();
cellStyle.Triggers.Add(animTrigger);
return cellStyle;
}
Here you go
Style PrepareAnimationStyle()
{
Trigger animTrigger = new Trigger();
animTrigger.Property = FrameworkElement.IsMouseOverProperty;
animTrigger.Value = true;
ColorAnimation strokeToGreen = new ColorAnimation((Color)ColorConverter.ConvertFromString("#FF66CC00"), TimeSpan.FromSeconds(0));
ColorAnimation strokeToSilver = new ColorAnimation(Colors.Silver, TimeSpan.FromSeconds(1));
ColorAnimation fillToGreen = new ColorAnimation((Color)ColorConverter.ConvertFromString("#FF66CC00"), TimeSpan.FromSeconds(0));
ColorAnimation fillToTransparent = new ColorAnimation(Colors.Transparent, TimeSpan.FromSeconds(1));
Storyboard sbEnter = new Storyboard();
Storyboard.SetTargetProperty(strokeToGreen, new PropertyPath("Stroke.Color"));
Storyboard.SetTargetProperty(fillToGreen, new PropertyPath("Fill.Color"));
sbEnter.Children.Add(strokeToGreen);
sbEnter.Children.Add(fillToGreen);
Storyboard sbExit = new Storyboard();
Storyboard.SetTargetProperty(strokeToSilver, new PropertyPath("Stroke.Color"));
Storyboard.SetTargetProperty(fillToTransparent, new PropertyPath("Fill.Color"));
sbExit.Children.Add(strokeToSilver);
sbExit.Children.Add(fillToTransparent);
animTrigger.EnterActions.Add(new BeginStoryboard() { Storyboard = sbEnter });
animTrigger.ExitActions.Add(new BeginStoryboard() { Storyboard = sbExit });
Style cellStyle = new Style();
cellStyle.Triggers.Add(animTrigger);
return cellStyle;
}
in order to make it work properly make sure to set a fill and stroke while you add the cell
example
Style cellStyle = PrepareAnimationStyle(); //this line is out side of the cell loop
....
rect.Fill = new SolidColorBrush(Colors.Transparent);
rect.Stroke = new SolidColorBrush(Colors.Silver);
rect.Style = cellStyle;
Related
My aim is to create a textBlock containing a name, after doing something with the method GetThings() I want an animation to play on the textBox basically moving it out of the view. as it is being animated the next textBlock is created with the next name.
But when I try and run the program I get the error:
No installed components were detected. Cannot resolve TargetProperty
(UIElement.RenderTransform).(CompositeTransform.TranslateY) on
specified object.
There is probably a better way of doing this, but I am limited in terms of my ability and would appreciate any help on the current issue.
Below is the code for the project:
await Task.Run(async () =>
{
TextBlock tb = null;
foreach (KeyValuePair<string, string> s in things)
{
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
TextBlock _txtBlock = new TextBlock()
{
Text = s.Key,
Margin = new Thickness(131, 0, 0, 0),
FontSize = 26,
Height = 40,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
Width = 168,
};
innerOverlay.Children.Add(_txtBlock);
tb = _txtBlock;
});
string tested = GetThings(s.Value);
if (tested == string.Empty)
{
MessageDialog failedMsg = new MessageDialog("failed", "problem");
failedMsg.Commands.Add(new UICommand("Exit"));
IUICommand command = await failedMsg.ShowAsync();
if (command.Label.Equals("Exit", StringComparison.CurrentCultureIgnoreCase))
{
Windows.UI.Xaml.Application.Current.Exit();
}
return;
}
else
{
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
var animation = new DoubleAnimation
{
EnableDependentAnimation = true,
To = 40,
Duration = new Duration(TimeSpan.FromMilliseconds(500)),
};
Storyboard.SetTarget(animation, tb);
Storyboard.SetTargetProperty(animation, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
var sb = new Storyboard();
sb.Children.Add(animation);
sb.Begin();
});
thingGroup.Add(s.Key, tested);
}
}
});
It seems that you are having questions about how to animate the transformation of the TextBlock. #Clemens is right, you will need to create a CompositeTransform object and assign it to the RenderTransform property of the TextBlock first.
I've made a simple demo here. You could refer to it and adjust it to your real scenario.
Code:
TextBlock _txtBlock = new TextBlock()
{
Text = "Frist One",
//Margin = new Thickness(131, 0, 0, 0),
FontSize = 26,
Height = 40,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
Width = 168,
};
RootGrid.Children.Add(_txtBlock);
//create a CompositeTransform for the TextBlock
CompositeTransform TextBlockTransform = new CompositeTransform();
_txtBlock.RenderTransform = TextBlockTransform;
//Create animation to animate the CompositeTransform
Storyboard storyboard = new Storyboard();
DoubleAnimation animation = new DoubleAnimation();
animation.From = 0;
animation.To = 40;
animation.Duration = new Duration(TimeSpan.FromMilliseconds(500));
Storyboard.SetTarget(animation, _txtBlock);
Storyboard.SetTargetProperty(animation, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
storyboard.Children.Add(animation);
storyboard.Begin();
You could get more information about Transforms and Animation here: Transforms overview, DoubleAnimation Class and CompositeTransform Class
I am using MSDN example to setup the animation of Width of a Rectangle in C3 UWP.
Here is the code of the sample:
private void Create_And_Run_Animation()
{
// Create a red rectangle that will be the target
// of the animation.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 0;
myRectangle.Height = 20;
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myRectangle.Fill = myBrush;
// Create the transform
TranslateTransform stretchTransform = new TranslateTransform();
stretchTransform.X = 0;
stretchTransform.Y = 0;
myRectangle.RenderTransform = stretchTransform;
// Add the rectangle to the tree.
DefaultLayout.Children.Add(myRectangle);
myRectangle.Name = "myWidthAnimatedRectangle";
// Create a duration of 2 seconds.
Duration duration = new Duration(TimeSpan.FromSeconds(2));
// Create two DoubleAnimations and set their properties.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(3000));
Storyboard justintimeStoryboard = new Storyboard();
justintimeStoryboard.Duration = duration;
justintimeStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTarget(myDoubleAnimation, stretchTransform);
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
// Set the X property of the Transform to be the target property
Storyboard.SetTargetProperty(myDoubleAnimation, "X");
myDoubleAnimation.To = 300.0;
// Make the Storyboard a resource.
DefaultLayout.Resources.Add("justintimeStoryboard", justintimeStoryboard);
// Begin the animation.
justintimeStoryboard.Begin();
}
However, on Build, what it does is move the object and not change its width.
I need to animate width change.
However, on Build, what it does is move the object and not change its width. I need to animate width change.
Your code was used to animate the Rectangle's position, not its width. You could specify a default value for its width and animate its ScaleTransform.
If you have to use DoubleAnimation to animate its width, you need to set EnableDependentAnimation to true. Please check the following code sample:
private void Create_And_Run_Animation()
{
// Create a red rectangle that will be the target
// of the animation.
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 10;
myRectangle.Height = 20;
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myRectangle.Fill = myBrush;
// Add the rectangle to the tree.
DefaultLayout.Children.Add(myRectangle);
myRectangle.Name = "myWidthAnimatedRectangle";
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(3000));
Storyboard justintimeStoryboard = new Storyboard();
Storyboard.SetTargetProperty(myDoubleAnimation, "(Rectangle.Width)");
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
myDoubleAnimation.To = 300.0;
myDoubleAnimation.EnableDependentAnimation = true;
justintimeStoryboard.Children.Add(myDoubleAnimation);
// Make the Storyboard a resource.
DefaultLayout.Resources.Add("justintimeStoryboard", justintimeStoryboard);
// Begin the animation.
justintimeStoryboard.Begin();
}
I have some problem. This is my code behind:
var s = new Storyboard();
var dAnimation = new DoubleAnimation();
dAnimation.RepeatBehavior = RepeatBehavior.Forever;
dAnimation.AutoReverse = true;
dAnimation.EnableDependentAnimation = true;
dAnimation.From = 200;
dAnimation.To = 300;
Storyboard.SetTarget(dAnimation, viewBox);
Storyboard.SetTargetProperty(dAnimation, "Width");
dAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(2000));
s.Children.Add(dAnimation);
s.Begin();
viewBox is on Canvas and has just a few property: Canvas.Left, Canvas.Top, Height and Width. Code from codebehind working great with Opacity, but not working with Width or Height. Codebehind work when user pointer is entered. I want do it without triggers. Found some solutions for Silverlight and WPF:
WinRT/Metro Animation in code-behind
they are not working. I dont undersstand why it work with opacity and didn't work with Width and Height Any ideas?
You cannot animate Width with a DoubleAnimation, you need to use a DoubleAnimationUsingKeyFrames.
var animation = new DoubleAnimationUsingKeyFrames();
var frame = new EasingDoubleKeyFrame { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(2000)), Value = 300});
animation.KeyFrames.Add(frame);
Storyboard.SetTargetProperty(animation, "(FrameworkElement.Width)");
Storyboard.SetTarget(animation, viewBox);
Storyboard.Children.Add(animation);
I didn't check ViewBox,but I can with DoubleAnimation for Grid.
Code is like below
var s = new Storyboard();
var widthAnim = new DoubleAnimation()
{
To = w,
Duration=new Duration(TimeSpan.FromMilliseconds(duration))
};
widthAnim.EnableDependentAnimation = true;
Storyboard.SetTarget(widthAnim,elem);
Storyboard.SetTargetProperty(widthAnim,"Width");
s.Children.Add(widthAnim);
s.Begin();
My Code is like this.
I want to create Grid dynamically.
creation is success, but I can't animate it's color.
What is my mistake?
Grid[] grid = new Grid[99];
for (int i = 0; i < 10; i++) {
grid[i] = new Grid();
grid[i].Width = grid[i].Height = 100;
grid[i].Background = Brushes.WhiteSmoke;
Storyboard sb = new Storyboard();
ColorAnimation ca = new ColorAnimation(Colors.DarkTurquoise, TimeSpan.FromMilliseconds(250));
Storyboard.SetTarget(ca, grid[i]);
Storyboard.SetTargetProperty(ca, new PropertyPath("Fill.Color"));
sb.Children.Add(ca);
grid[i].MouseEnter += delegate(object sender2, MouseEventArgs e2) {
sb.Begin(this);
};
stackMain.Children.Add(grid[i]);
}
WPF Grid has no Fill property you will have to use Background
Storyboard.SetTargetProperty(ca, new PropertyPath("Background.Color"));
In addition to what sa_ddam has said, you would also have to create a Brush, since the built-in brushes (like Brushes.WhiteSmoke in your example) can't be animated.
grid[i].Background = new SolidColorBrush(Colors.WhiteSmoke);
...
Storyboard.SetTargetProperty(ca, new PropertyPath("Background.Color"));
It might also save some code if you omit the Storyboard and run the animation directly:
var brush = new SolidColorBrush(Colors.WhiteSmoke);
grid[i].Background = brush;
var ca = new ColorAnimation(Colors.DarkTurquoise, TimeSpan.FromMilliseconds(250));
grid[i].MouseEnter +=
(o, e) => brush.BeginAnimation(SolidColorBrush.ColorProperty, ca);
I am trying to get these ellipses to grow but I cannot figure out how to start the animation. This is my first attempt at WPF animation and I don't quite understand how it all works.
private void drawEllipseAnimation(double x, double y)
{
StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);
Ellipse e = new Ellipse();
e.Fill = Brushes.Yellow;
e.Stroke = Brushes.Black;
e.Height = 0;
e.Width = 0;
e.Opacity = .8;
canvas2.Children.Add(e);
Canvas.SetLeft(e, x);
Canvas.SetTop(e, y);
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 10;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, e.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Ellipse.HeightProperty));
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Ellipse.WidthProperty));
}
You don't need a Storyboard here. Just do
e.BeginAnimation(Ellipse.WidthProperty, myDoubleAnimation);
e.BeginAnimation(Ellipse.HeightProperty, myDoubleAnimation);
If you really need to do it with a Storyboard, you will have to add separate animations, one per animated property, to the Storyboard. And you have to call SetTarget instead of SetTargetName when you don't apply a name. Finally you'll need to start the Storyboard by calling Begin:
DoubleAnimation widthAnimation = new DoubleAnimation
{
From = 0,
To = 10,
Duration = TimeSpan.FromSeconds(5)
};
DoubleAnimation heightAnimation = new DoubleAnimation
{
From = 0,
To = 10,
Duration = TimeSpan.FromSeconds(5)
};
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Ellipse.WidthProperty));
Storyboard.SetTarget(widthAnimation, e);
Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(Ellipse.HeightProperty));
Storyboard.SetTarget(heightAnimation, e);
Storyboard s = new Storyboard();
s.Children.Add(widthAnimation);
s.Children.Add(heightAnimation);
s.Begin();