首页 > 技术文章 > WPF扇形展开动画实现

jisi2012 2014-02-19 16:26 原文

最近在实现WPF的图片展开动画,一些比较基础的动画效果的实现方法在网上都能够找到,而扇形展开动画一直没有找到,不知道是个人的搜索技术不行,还是本来实现的少。

于是,只能自己动手想办法实现这种效果,所幸,最后还是让我想到了实现的方法(路径动画模拟实现)。

图片的展开动画,这里都是设置了图片控件的OpacityMask属性,然后再动画中动态修改OpacityMask属性模板里面的某个属性值以达到想要的视觉效果。

最开始的时候,想模仿“旋转展开方法”来实现扇形展开的(一条直线,以一个端点做支点,旋转直线),不过发现端点控制修改后并不是自己想要的效果,最后看了一些基于路径的动画,想着是否使用路径,其中两个端点固定,再移动另外一个端点来显示出图片,最后实验证明确实是可以的。

下面就分享一下实现代码:

1) 下面是前端用来展现动画的图片。这里因为要实现移出移入等效果,所以使用了Canvas作为父级控件。

1  <Canvas Grid.Row="1" Name="canvas1" Background="Transparent" ClipToBounds="True">
2       <Image Name="aniCon" Source="../Images/a.jpg"  Canvas.Left="40" Canvas.Top="25" Width="500">
3       </Image>
4  </Canvas>
View Code

2)接下来是Image的OpacityMask属性代码(这里使用资源实现,当然也可以使用C#实现再赋值给Image)

 1  <Style TargetType="{x:Type ContentPresenter}" x:Key="fanOutStyle">
 2         <Setter Property="UIElement.OpacityMask">
 3             <Setter.Value>
 4                 <DrawingBrush Stretch="None" AlignmentX="Left" AlignmentY="Top">
 5                     <DrawingBrush.Drawing>
 6                         <GeometryDrawing Brush="LightGray">
 7                             <GeometryDrawing.Geometry>
 8                                 <GeometryGroup>
 9                                     <PathGeometry>
10                                         <PathGeometry.Figures>
11                                             <PathFigureCollection>
12                                                 <PathFigure IsClosed="True" StartPoint="290,182" x:Name="mFigure">
13                                                     <PathFigure.Segments>
14                                                         <PathSegmentCollection>
15                                                             <LineSegment Point="40,25" />
16                                                             <LineSegment Point="45,25"  x:Name="aa"/>
17                                                         </PathSegmentCollection>
18                                                     </PathFigure.Segments>
19                                                 </PathFigure>
20                                                 <PathFigure IsClosed="True" StartPoint="290,182">
21                                                     <PathFigure.Segments>
22                                                         <PathSegmentCollection>
23                                                             <LineSegment Point="540,25" />
24                                                             <LineSegment Point="540,30"/>
25                                                         </PathSegmentCollection>
26                                                     </PathFigure.Segments>
27                                                 </PathFigure>
28                                                 <PathFigure IsClosed="True" StartPoint="290,182" >
29                                                     <PathFigure.Segments>
30                                                         <PathSegmentCollection>
31                                                             <LineSegment Point="540,340" />
32                                                             <LineSegment Point="535,340"/>
33                                                         </PathSegmentCollection>
34                                                     </PathFigure.Segments>
35                                                 </PathFigure>
36                                                 <PathFigure IsClosed="True" StartPoint="290,182">
37                                                     <PathFigure.Segments>
38                                                         <PathSegmentCollection>
39                                                             <LineSegment Point="40,340" />
40                                                             <LineSegment Point="40,335"/>
41                                                         </PathSegmentCollection>
42                                                     </PathFigure.Segments>
43                                                 </PathFigure>
44                                             </PathFigureCollection>
45                                         </PathGeometry.Figures>
46                                     </PathGeometry>
47                                 </GeometryGroup>
48                             </GeometryDrawing.Geometry>
49                         </GeometryDrawing>
50                     </DrawingBrush.Drawing>
51                 </DrawingBrush>
52             </Setter.Value>
53         </Setter>
54     </Style>
View Code

3)端点移动的路径,这里将路径分成了4段,不分段会导致最后图片展开完成后是显示不完整的

 1  <PathGeometry x:Key="path1">
 2         <PathFigure StartPoint="40,25">
 3             <PathFigure.Segments>
 4                 <PathSegmentCollection>
 5                     <LineSegment Point="540,25" />
 6                 </PathSegmentCollection>
 7             </PathFigure.Segments>
 8         </PathFigure>
 9     </PathGeometry>
10     <PathGeometry x:Key="path2">
11         <PathFigure  StartPoint="540,25">
12             <PathFigure.Segments>
13                 <PathSegmentCollection>
14                     <LineSegment Point="540,340"/>
15                 </PathSegmentCollection>
16             </PathFigure.Segments>
17         </PathFigure>
18     </PathGeometry>
19     <PathGeometry x:Key="path3">
20         <PathFigure  StartPoint="540,340">
21             <PathFigure.Segments>
22                 <PathSegmentCollection>
23                     <LineSegment Point="40,340" />
24                 </PathSegmentCollection>
25             </PathFigure.Segments>
26         </PathFigure>
27     </PathGeometry>
28     <PathGeometry x:Key="path4">
29         <PathFigure  StartPoint="40,340">
30             <PathFigure.Segments>
31                 <PathSegmentCollection>
32                     <LineSegment Point="40,25" />
33                 </PathSegmentCollection>
34             </PathFigure.Segments>
35         </PathFigure>
36     </PathGeometry>
View Code

4)动画,使用基于路径的动画

 1  <Storyboard x:Key="fanOut">
 2             <PointAnimationUsingPath Storyboard.TargetName="aniCon"
 3                                                          Storyboard.TargetProperty="OpacityMask.Drawing.Geometry.Children[0].Figures[0].Segments[1].Point"
 4                                                              PathGeometry="{StaticResource path1}"
 5                                                          Duration="0:0:2" BeginTime="0:0:0"/>
 6             <PointAnimationUsingPath Storyboard.TargetName="aniCon"
 7                                                          Storyboard.TargetProperty="OpacityMask.Drawing.Geometry.Children[0].Figures[1].Segments[1].Point"
 8                                                              PathGeometry="{StaticResource path2}"
 9                                                          Duration="0:0:2" BeginTime="0:0:2"/>
10             <PointAnimationUsingPath Storyboard.TargetName="aniCon"
11                                                          Storyboard.TargetProperty="OpacityMask.Drawing.Geometry.Children[0].Figures[2].Segments[1].Point"
12                                                              PathGeometry="{StaticResource path3}"
13                                                          Duration="0:0:2" BeginTime="0:0:4"/>
14             <PointAnimationUsingPath Storyboard.TargetName="aniCon"
15                                                          Storyboard.TargetProperty="OpacityMask.Drawing.Geometry.Children[0].Figures[3].Segments[1].Point"
16                                                              PathGeometry="{StaticResource path4}"
17                                                          Duration="0:0:2" BeginTime="0:0:6"/>
18         </Storyboard>
View Code

以上便是使用的代码了,这边用的都是Xaml来实现。动画使用按钮控件触发即可。

在实现过程中,也是遇到了各种问题,特别是Storyboard的TargetProperty的属性路径获取,试验了好久才找到正确的属性路径。当然,结果是喜人的。使用基于路径的动画来实现,代码还是挺多的,感觉挺复杂的,也许还可以简化,不过暂时就先这样了,后面要是有简化了再修改好了。

 

推荐阅读