Reputation: 331
I was playing around with WPF animations and tried to animate the border of a rectangle in the way of a wandering stroke (kind of marching ants with only one ant) and came up with the following working code:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="WindowTest.MainWindow"
Height="454.719" Width="429.847" ResizeMode="NoResize">
<Window.Resources>
<Storyboard x:Key="MarchingAnts">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="rectangle"
Storyboard.TargetProperty="(Shape.StrokeDashOffset)"
RepeatBehavior="Forever">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:03.000000" Value="-385"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource MarchingAnts}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Canvas x:Name="canvas" Background="#FF262626">
<Rectangle Fill="#14FFFFFF"
Stroke="Red"
x:Name="rectangle" Width="400" Height="400"
StrokeDashOffset="-385" StrokeDashArray='0, 0, 100,285' StrokeThickness="4"
RadiusX="25" RadiusY="25"
Canvas.Left="10" Canvas.Top="10">
</Rectangle>
</Canvas>
</Grid>
</Window>
So I have basically one 'ant' with the length of 100 wandering around a square with a width of 400. Now I wanted to find a way to put a gradient on the 'ant', for example to fade it out from 50% to the end.
Is there a way to add such to the animated StrokeDashArray or should I create the whole thing differently from the beginning? Requirement would be to have the animation on top of a border or rectangle.
Any hints are welcome!
update: as in Chris answer and my comment .. the intended look would be like this: with the dash wandering around the rectangle
Upvotes: 2
Views: 3943
Reputation: 23280
I have an example of ants here
You can apply a Gradient to your stroke, as example;
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Red" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Stroke>
However it will apply the gradient to the entire stroke and not an individual dash as I think you're implying you would rather have. What you're asking for there is not possible.
However, you can fake it with an illusion to sort of the same effect without the DashArray and animating the Gradient EndPoint
and StartPoint
(Shown in the Rectangle.Stroke example above) around the object from start to finish.
Quickie Concept Example:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="GradientChaser" RepeatBehavior="Forever">
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.StartPoint)"
Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:0.5" Value="0.855,0.148"/>
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.852,0.855"/>
<EasingPointKeyFrame KeyTime="0:0:1.5" Value="0.148,0.855"/>
<EasingPointKeyFrame KeyTime="0:0:2" Value="0.144,0.149"/>
<EasingPointKeyFrame KeyTime="0:0:2.5" Value="0,0"/>
</PointAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.EndPoint)"
Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:0.5" Value="0.145,0.852"/>
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.148,0.145"/>
<EasingPointKeyFrame KeyTime="0:0:1.5" Value="0.852,0.145"/>
<EasingPointKeyFrame KeyTime="0:0:2" Value="0.856,0.851"/>
<EasingPointKeyFrame KeyTime="0:0:2.5" Value="0,1"/>
</PointAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource GradientChaser}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Rectangle x:Name="rectangle" Width="250" Height="250"
HorizontalAlignment="Center" VerticalAlignment="Center"
StrokeThickness="10">
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Red" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
</Grid>
</Window>
Quickie Concept Example Result:
ADDENDUM:
Unfortunately I don't have free time to tweak it and make it perfect to do your work but hopefully it will communicate the concept of how you can achieve the effect with the stroke gradient technique you're after.
Quickie Updated code:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Storyboard x:Key="GradientChaser" RepeatBehavior="Forever">
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.StartPoint)" Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:0.5" Value="0.855,0.148"/>
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.852,0.855"/>
<EasingPointKeyFrame KeyTime="0:0:1.5" Value="0.148,0.855"/>
<EasingPointKeyFrame KeyTime="0:0:2" Value="0.144,0.149"/>
<EasingPointKeyFrame KeyTime="0:0:2.5" Value="0,0"/>
</PointAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.EndPoint)" Storyboard.TargetName="rectangle">
<EasingPointKeyFrame KeyTime="0:0:0.5" Value="0.145,0.852"/>
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.148,0.145"/>
<EasingPointKeyFrame KeyTime="0:0:1.5" Value="0.852,0.145"/>
<EasingPointKeyFrame KeyTime="0:0:2" Value="0.856,0.851"/>
<EasingPointKeyFrame KeyTime="0:0:2.5" Value="0,1"/>
</PointAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="GradientChaserOverlay" RepeatBehavior="Forever">
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.StartPoint)" Storyboard.TargetName="rectangle2">
<EasingPointKeyFrame KeyTime="0:0:0.5" Value="0.146,0.146"/>
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.502,-0.001"/>
<EasingPointKeyFrame KeyTime="0:0:1.5" Value="0.85,0.142"/>
<EasingPointKeyFrame KeyTime="0:0:2" Value="0.863,0.845"/>
<EasingPointKeyFrame KeyTime="0:0:2.5" Value="-0.001,0.498"/>
</PointAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Stroke).(LinearGradientBrush.EndPoint)" Storyboard.TargetName="rectangle2">
<EasingPointKeyFrame KeyTime="0:0:0.5" Value="0.854,0.854"/>
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.498,1.001"/>
<EasingPointKeyFrame KeyTime="0:0:1.5" Value="0.15,0.858"/>
<EasingPointKeyFrame KeyTime="0:0:2" Value="0.137,0.155"/>
<EasingPointKeyFrame KeyTime="0:0:2.5" Value="1.001,0.502"/>
</PointAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource GradientChaser}"/>
<BeginStoryboard Storyboard="{StaticResource GradientChaserOverlay}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Rectangle x:Name="rectangle" Width="250" Height="250" HorizontalAlignment="Center" VerticalAlignment="Center" StrokeThickness="10">
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Red" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
<Rectangle x:Name="rectangle2" Width="250" Height="250" HorizontalAlignment="Center" VerticalAlignment="Center" StrokeThickness="10">
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="1,0.501" StartPoint="0,0.499">
<GradientStop Color="White" Offset="0.35"/>
<GradientStop Color="Transparent" Offset="0.342"/>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
</Grid>
</Window>
Quickie Concept Result (will require some tweaking, but hey, SO isn't a free code work service anyway right? :) Oh, and sorry for the crappy .gif quality.
Hope this helps, Cheers!
Upvotes: 8