C# 如何在WPF中沿圆形路径设置图像动画?
我需要创建一个相当复杂的动画,涉及WPF中的图像,其中图像必须沿圆形路径移动 这是我的xaml:C# 如何在WPF中沿圆形路径设置图像动画?,c#,wpf,animation,C#,Wpf,Animation,我需要创建一个相当复杂的动画,涉及WPF中的图像,其中图像必须沿圆形路径移动 这是我的xaml: <ControlTemplate x:Key="ValveStyle" TargetType="{x:Type CheckBox}"> <ControlTemplate.Resources> <PathGeometry x:Key="CirclePathGeometry" PresentationOptions:Freeze="True">
<ControlTemplate x:Key="ValveStyle" TargetType="{x:Type CheckBox}">
<ControlTemplate.Resources>
<PathGeometry x:Key="CirclePathGeometry" PresentationOptions:Freeze="True">
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="340,120">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="100,50" RotationAngle="0" IsLargeArc="False" SweepDirection="CounterClockwise"
Point="-30,120" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</ControlTemplate.Resources>
<Viewbox Stretch="Uniform">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.2000000" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Unchecked" />
<VisualState x:Name="Checked">
<Storyboard>
<!--DoubleAnimationUsingPath BeginTime="00:00:00" Storyboard.TargetName="image3" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Source="X"
DoubleAnimationUsingPath.PathGeometry="{StaticResource CirclePathGeometry}" />
<DoubleAnimationUsingPath BeginTime="00:00:00" Storyboard.TargetName="image3" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Source="Y"
DoubleAnimationUsingPath.PathGeometry="{StaticResource CirclePathGeometry}" /-->
<MatrixAnimationUsingPath Storyboard.TargetName="Image3MatrixTransform" Storyboard.TargetProperty="Matrix"
MatrixAnimationUsingPath.PathGeometry="{StaticResource CirclePathGeometry}" />
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
Storyboard.TargetName="image1"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="-90" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
Storyboard.TargetName="image2"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="-90" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
Storyboard.TargetName="image"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="-90" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<VisualStateManager.CustomVisualStateManager>
<ic:ExtendedVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<Canvas Width="685" Height="527">
<Image Source="/VT;component/Images/Valve121.1-Base.png" Stretch="Fill" />
<Image x:Name="image" Source="/VT;component/Images/Valve121.1-LeftBar1.png" Stretch="Fill"
Canvas.Left="61.991" Canvas.Top="49.329" RenderTransformOrigin="0.286,0.5428">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Image.RenderTransform>
</Image>
<Image x:Name="image2" Source="/VT;component/Images/Valve121.1-RightBar.png" Stretch="Fill"
Canvas.Left="436.491" Canvas.Top="49.388" RenderTransformOrigin="0.249,0.756">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Image.RenderTransform>
</Image>
<Image x:Name="image3" Source="/VT;component/Images/Valve121.1-HzBar.png" Stretch="Fill"
Canvas.Left="277.491" Canvas.Top="58.345">
<Image.RenderTransform>
<MatrixTransform x:Name="Image3MatrixTransform" />
</Image.RenderTransform>
</Image>
<Image Source="/VT;component/Images/Valve121.1-Overlay.png" Stretch="Fill" />
<Image x:Name="image1" Source="/VT;component/Images/Valve121.1-LeftBar2.png" Stretch="Fill"
Canvas.Left="129.824" Canvas.Top="24.661" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Image.RenderTransform>
</Image>
<Path Stroke="Blue" StrokeThickness="10" RenderTransformOrigin="-0.333,-0.227">
<Path.Data>
<PathGeometry>
<PathFigureCollection>
<PathFigure StartPoint="340,120">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="100,50" RotationAngle="0" IsLargeArc="False" SweepDirection="CounterClockwise"
Point="-30,120" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Viewbox>
</ControlTemplate>
我面临着几个问题:
- 图像(图3)似乎没有沿着我设置的路径正确移动,所以我想我在那里犯了一个错误李>
- 图像(image3)的动画在所有其他动画完成后开始。我想所有的动画在同一时间开始
有可能在WPF中制作这样的动画吗?如果是这样,我该如何实现这一点?按如下方式定义
主窗口
(或页面
)类:
<Window x:Class="TestCustomTab.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<PathGeometry x:Key="path" Figures="M 0,50 A 50,50 0 1 1 100,50 " />
<Storyboard x:Key="ellipseSB">
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource path}"
Duration="0:0:5" RepeatBehavior="Forever"
AutoReverse="True" Source="X" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource path}"
Duration="0:0:5" RepeatBehavior="Forever"
AutoReverse="True" Source="Y" />
</Storyboard>
</Window.Resources>
<Grid x:Name="grid">
<Canvas>
<Ellipse x:Name="ellipse" Width="10" Height="10" Stroke="Black" Fill="Black"
RenderTransformOrigin="0.5,0.5" />
<Path Stroke="Red" StrokeThickness="1" Canvas.Left="5" Canvas.Top="5"
Data="{StaticResource path}"/>
</Canvas>
<Button VerticalAlignment="Bottom" Content="Start" Click="Button_Click"/>
</Grid>
</Window>
它将沿着定义的弧段(半个圆)精确设置10×10椭圆的动画
希望这能有所帮助。我也遇到过同样的情况。尤金的例子很有帮助。我将其稍微延伸以形成完整的圆圈:
<Window x:Class="TestCustomTab.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300">
<Window.Resources>
<PathGeometry x:Key="pathUpperHalf" Figures="M 0,50 A 50,50 0 1 1 100,50 " />
<PathGeometry x:Key="pathLowerHalf" Figures="M 100,50 A 50,50 0 1 1 0,50" />
<Storyboard x:Key="ellipseSB" RepeatBehavior="Forever">
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource pathUpperHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:0" Source="X" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource pathUpperHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:0" Source="Y" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource pathLowerHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:1" Source="X" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource pathLowerHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:1" Source="Y" />
</Storyboard>
</Window.Resources>
<Grid x:Name="grid">
<Canvas>
<Ellipse x:Name="ellipse" Width="10" Height="10" Stroke="Black" Fill="Black" RenderTransformOrigin="0.5,0.5" />
<Path Stroke="Blue" StrokeThickness="1" Canvas.Left="5" Canvas.Top="5" Data="{StaticResource pathUpperHalf}"/>
<Path Stroke="Red" StrokeThickness="1" Canvas.Left="5" Canvas.Top="5" Data="{StaticResource pathLowerHalf}"/>
</Canvas>
<Button VerticalAlignment="Bottom" Content="Start" Click="Button_Click"/>
</Grid>
</Window>
我建议对这些任务使用Expression Blend。网上有几个教程解释如何解决你刚才提到的任务。我不喜欢使用WYIWYG应用程序,但对于动画或创建复杂的几何图形,这些应用程序通常都是黄金。@Torsten:我已经在使用Blend,我同意它是一个非常有用的工具,我无法想象没有它做这类事情;-)。。。但是,这仍然是一些高级动画,我想我达到了混合的极限,或者,有一个功能我忽略了……好吧,我有点担心你会说XD,然后我相信你也知道可以并行地设置对象的动画。我记得使用本教程入门:我的猜测是简单地为您的image3定义另一个时间线(或者为每个对象定义一个单独的时间线)。分组也有助于让所有对象一起移动。也许这些提示又太琐碎了,我希望它们不是。FWIW:没有必要声明两对不同的动画来获得完整的循环。只需将原始圆延伸至起点即可;唯一的“问题”是,如果指定完全相同的点,则不会绘制任何内容。但您可以从其中一个坐标中减去一个非常小的量(例如0.0001)(在上述示例中,在靠近末端时变化最快的那个…Y
),然后WPF将知道如何进行长距离的变换。例如,使用Figures=“M 0,50 A 50,50 0 1 1 0,49.9999”
。
<Window x:Class="TestCustomTab.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300">
<Window.Resources>
<PathGeometry x:Key="pathUpperHalf" Figures="M 0,50 A 50,50 0 1 1 100,50 " />
<PathGeometry x:Key="pathLowerHalf" Figures="M 100,50 A 50,50 0 1 1 0,50" />
<Storyboard x:Key="ellipseSB" RepeatBehavior="Forever">
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource pathUpperHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:0" Source="X" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource pathUpperHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:0" Source="Y" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Left)"
PathGeometry="{StaticResource pathLowerHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:1" Source="X" />
<DoubleAnimationUsingPath Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Canvas.Top)"
PathGeometry="{StaticResource pathLowerHalf}"
Duration="0:0:1" RepeatBehavior="1x" AutoReverse="False" BeginTime="0:0:1" Source="Y" />
</Storyboard>
</Window.Resources>
<Grid x:Name="grid">
<Canvas>
<Ellipse x:Name="ellipse" Width="10" Height="10" Stroke="Black" Fill="Black" RenderTransformOrigin="0.5,0.5" />
<Path Stroke="Blue" StrokeThickness="1" Canvas.Left="5" Canvas.Top="5" Data="{StaticResource pathUpperHalf}"/>
<Path Stroke="Red" StrokeThickness="1" Canvas.Left="5" Canvas.Top="5" Data="{StaticResource pathLowerHalf}"/>
</Canvas>
<Button VerticalAlignment="Bottom" Content="Start" Click="Button_Click"/>
</Grid>
</Window>