找回密码
 立即注册
首页 业界区 安全 WPF骨架屏控件(Skeleton)

WPF骨架屏控件(Skeleton)

佴莘莘 2025-5-30 20:22:08
 一.骨架屏介绍        
骨架屏(Skeleton)是一种用于提升用户体验的界面设计技术,通过在页面数据加载前展示简化的页面框架结构(如占位符、灰色块等),模拟真实内容的布局,避免用户面对空白页面或长时间等待的焦虑感。
特点及原理:
1.占位展示:骨架屏由基本框架和占位元素(如线条、矩形)组成,形状与实际内容布局一致,例如用短横线模拟文本、矩形框模拟图片区域。
2.动态替换:当真实数据加载完成后,骨架屏会被无缝替换为实际内容,通过渐变或动画实现平滑过渡。
3.设计原则:通常采用低饱和度色调(如灰色)和简洁的动画效果,避免视觉干扰,同时传达“加载中”的信号。
优势:1.提升感知速度:虽然不缩短实际加载时间,但通过视觉反馈让用户感觉加载更快。
2.降低跳出率:减少因空白页面导致的用户流失。
3.兼容性:适用于各种异步加载场景。
二.骨架屏控件设计
2.1 骨架的构成        
  从骨架屏的特点可以看出,骨架主要由方形、圆形、条形几种基本图案构成,将它们以不同的方式排列,即可完成骨架的搭建,下面我们来看看几种比较典型的情况。
1.png

图 2.1.1 文本骨架屏

图 2.1.2 带操作的骨架屏
3.png

图 2.1.3 带头像的骨架屏
4.png

图 2.1.4 带图片和视频的骨架屏
2.2 骨架的绘制      
  我们来看看怎么将这些方形、圆形、条形画到控件上,如果按常规的方式,先使用一个布局面板控件设计好骨架,然后再往里面填充Rectangle或Ellipse,这样就能达到骨架屏的效果,但是如果每一种布局都这样去写一遍,那就太繁琐了,得不偿失。如果通过一些参数去自动设置布局及填充,理论上是可以的,但是这种方式也有一个问题,那就是动画,为了表示骨架下的页面元素正在加载,一般会给它设计一个光影流动的效果,如果按照这种方式,每个骨架组件都是独立的,那么我们控制光影流动(渐变画刷)就会变得比较麻烦,虽然也有办法实现,但是从代码量和性能上来说都不是一个好的选择。那么有没有可以单独添加图形,又方便控制渐变效果,还性能好的控件呢,答案是有,它就是Path,我们可以往Path中添加各种图形,又可以整体控制它的渐变效果。以下是简单的示例:
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path>
复制代码
2.3 骨架的排列      
  通过以上示例代码可以看出,在Path中添加图形需要设置关键属性Rect,Rect需要4个double类型的参数,前两个参数为X和Y坐标,后两个为Width和Height,只要设置了正确的参数,就可以显示出我们需要的骨架,但是如果每次都要去自己计算坐标和尺寸,那肯定不太现实,所以我们需要设计一种排列规则,只要设置参数就可以让它按照正确的方式排列。        在真实的项目中,页面元素的布局千变万化,所以骨架的排列应考虑到是否能够满足各种不同的情况,同时还要兼顾易用性,不能设计得太复杂,学习成本越低越好。基于以上考虑,我们可以借鉴Grid的布局逻辑,我们都知道在Grid中布局需要预先设置行数和列数,并在添加到Grid中的控件上设置Grid.Row和Grid.Column附加属性来确定当前控件是属于哪个位置,请看以下代码:
  1. <Grid>
  2.     <Grid.RowDefinitions>
  3.        <RowDefinition Height="*" />
  4.        <RowDefinition Height="*" />
  5.     </Grid.RowDefinitions>
  6.     <Grid.ColumnDefinitions>
  7.        <ColumnDefinition Width="Auto" />
  8.        <ColumnDefinition Width="10" />
  9.        <ColumnDefinition Width="*" />
  10.     </Grid.ColumnDefinitions>
  11.     <Rectangle Grid.Row="0" Grid.Column="0"/>
  12. </Grid>
复制代码
  Grid的这种设计可以应对各种复杂的布局,我们只是为了显示骨架,显然不需要这么复杂的功能,我们可以将它精简一下,只要能满足布局需求就可以了,我们可以将Path中添加的RectangleGeometry的Width和Height使用Grid中设置Width和Height的方式来设置,Grid中的Width和Height都是GridLengh类型,它使用自动(Auto)、像素(Pixel)、比例(Star)三种方式来设置Width和Height,由于我们不会有根据内容来确定宽度和高度的需求,所我们实际只会用到像素(Pixel)和比例(Star)两种方式来布局。      
  基于以上理论,我们可以将业务大致抽象,形成以下设计:
1.Skeleton类      
  骨架控件,有一个Items属性,该属性可以设置SkeletonItem或SkeletonGroup类型值,该属性包含了所有的骨架绘制参数。
2.SkeletonItem类      
  骨架项,所有能看到的部分(方形、圆形、条形)都由它绘制、可以通过Width和Height属性控制宽度和高度,可以通过Margin属性设置边距,可以通过HorizontalAlignment和VerticalAlignment属性设置水平和垂直对齐方向,可以通过RadiusX和RadiusY属性设置圆角半径,可以通过IsVisible属性控制可见性。
3.SkeletonGroup类      
  骨架分组,可以将多个SkeletonItem和SkeletonGroup放置到Children属性中,形成嵌套关系,再配合Orientation属性设置排列方向,就可以实现复杂的布局,除此之外,它还可以像SkeletonItem一样,设置Width、Height、HorizontalAlignment、VerticalAlignment等属性。
2.3 动画效果      
  光影效果只需要控制画刷的横向位置变化就行了,这里我们使用的是RadialGradientBrush来填充Path的背景,我们可以添加一个动画,控制RadialGradientBrush的RelativeTransform属性中的TranslateTransform参数。
Path代码:
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  16.    <Path.Fill>
  17.        <RadialGradientBrush>
  18.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  19.            <GradientStop Color="White" Offset="0"/>
  20.        </RadialGradientBrush>
  21.    </Path.Fill>
  22.    <Path.Data>
  23.        <GeometryGroup>
  24.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  25.            <RectangleGeometry Rect="105,0,100,100" />
  26.            <RectangleGeometry Rect="210,40,100,20" />
  27.        </GeometryGroup>
  28.    </Path.Data>
  29. </Path><Storyboard
  30.     AutoReverse="False"
  31.     RepeatBehavior="Forever">
  32.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  33.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  34.     </DoubleAnimationUsingKeyFrames>
  35. </Storyboard><Storyboard
  36.     AutoReverse="False"
  37.     RepeatBehavior="Forever">
  38.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  39.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  40.     </DoubleAnimationUsingKeyFrames>
  41. </Storyboard><Storyboard
  42.     AutoReverse="False"
  43.     RepeatBehavior="Forever">
  44.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  45.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  46.     </DoubleAnimationUsingKeyFrames>
  47. </Storyboard>      
复制代码
动画代码:
  1. <Storyboard
  2.     AutoReverse="False"
  3.     RepeatBehavior="Forever">
  4.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  5.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  6.     </DoubleAnimationUsingKeyFrames>
  7. </Storyboard>
复制代码
三.骨架屏控件实现
  根据以上设计思路,我们需要Skeleton、SkeletonItem、SkeletonGroup三个类来实现骨架功能,其中SkeletonItem、SkeletonGroup同属骨架的组成部分,它们有一些相同的属性,所以它们可以抽象出一个共同的父类SkeletonComponent,以下是部分关键代码,仅供参考。
3.1 Skeleton
  1. [ContentProperty("Items")]
  2. public class Skeleton : FrameworkElement
  3. {
  4.     public SkeletonComponent Items
  5.     {
  6.        get { return (SkeletonComponent)GetValue(ItemsProperty); }
  7.        set { SetValue(ItemsProperty, value); }
  8.     }
  9.     public static readonly DependencyProperty ItemsProperty =
  10.        DependencyProperty.Register("Items", typeof(SkeletonComponent), typeof(Skeleton), new FrameworkPropertyMetadata(null));
  11. }
复制代码
3.2 SkeletonComponent
  1. public abstract class SkeletonComponent : DependencyObject
  2. {
  3.     public GridLength Width
  4.     {
  5.        get { return (GridLength)GetValue(WidthProperty); }
  6.        set { SetValue(WidthProperty, value); }
  7.     }
  8.     public static readonly DependencyProperty WidthProperty =
  9.        DependencyProperty.Register("Width", typeof(GridLength), typeof(SkeletonComponent), new PropertyMetadata(new GridLength(1.0, GridUnitType.Star)));
  10.     public GridLength Height
  11.     {
  12.        get { return (GridLength)GetValue(HeightProperty); }
  13.        set { SetValue(HeightProperty, value); }
  14.     }
  15.     public static readonly DependencyProperty HeightProperty =
  16.        DependencyProperty.Register("Height", typeof(GridLength), typeof(SkeletonComponent), new PropertyMetadata(new GridLength(1.0, GridUnitType.Star));
  17.     public Thickness Margin
  18.     {
  19.        get { return (Thickness)GetValue(MarginProperty); }
  20.        set { SetValue(MarginProperty, value); }
  21.     }
  22.     public static readonly DependencyProperty MarginProperty =
  23.        DependencyProperty.Register("Margin", typeof(Thickness), typeof(SkeletonComponent));
  24.     public HorizontalAlignment HorizontalAlignment
  25.     {
  26.        get { return (HorizontalAlignment)GetValue(HorizontalAlignmentProperty); }
  27.        set { SetValue(HorizontalAlignmentProperty, value); }
  28.     }
  29.     public static readonly DependencyProperty HorizontalAlignmentProperty =
  30.        DependencyProperty.Register("HorizontalAlignment", typeof(HorizontalAlignment), typeof(SkeletonComponent), new PropertyMetadata(HorizontalAlignment.Left));
  31.     public VerticalAlignment VerticalAlignment
  32.     {
  33.        get { return (VerticalAlignment)GetValue(VerticalAlignmentProperty); }
  34.        set { SetValue(VerticalAlignmentProperty, value); }
  35.     }
  36.     public static readonly DependencyProperty VerticalAlignmentProperty =
  37.        DependencyProperty.Register("VerticalAlignment", typeof(VerticalAlignment), typeof(SkeletonComponent), new PropertyMetadata(VerticalAlignment.Top));
  38. }
复制代码
3.3 SkeletonItem
  1. public class SkeletonItem : SkeletonComponent
  2. {
  3.     public double RadiusX
  4.     {
  5.        get { return (double)GetValue(RadiusXProperty); }
  6.        set { SetValue(RadiusXProperty, value); }
  7.     }
  8.     public static readonly DependencyProperty RadiusXProperty =
  9.        DependencyProperty.Register("RadiusX", typeof(double), typeof(SkeletonItem), new PropertyMetadata(0d));
  10.     public double RadiusY
  11.     {
  12.        get { return (double)GetValue(RadiusYProperty); }
  13.        set { SetValue(RadiusYProperty, value); }
  14.     }
  15.     public static readonly DependencyProperty RadiusYProperty =
  16.        DependencyProperty.Register("RadiusY", typeof(double), typeof(SkeletonItem), new PropertyMetadata(0d));
  17.     public bool IsVisible
  18.     {
  19.        get { return (bool)GetValue(IsVisibleProperty); }
  20.        set { SetValue(IsVisibleProperty, value); }
  21.     }
  22.     public static readonly DependencyProperty IsVisibleProperty =
  23.        DependencyProperty.Register("IsVisible", typeof(bool), typeof(SkeletonItem), new PropertyMetadata(true));
  24. }
复制代码
3.4 SkeletonGroup
  1. [ContentProperty("Children")]
  2. public class SkeletonGroup : SkeletonComponent
  3. {
  4.    public SkeletonComponentCollection Children
  5.     {
  6.        get { return (SkeletonComponentCollection)GetValue(ChildrenProperty); }
  7.        private set { SetValue(ChildrenProperty, value); }
  8.     }
  9.    public static readonly DependencyProperty ChildrenProperty =
  10.        DependencyProperty.Register("Children", typeof(SkeletonComponentCollection), typeof(SkeletonGroup), new PropertyMetadata(null));
  11.    public Orientation Orientation
  12.     {
  13.        get { return (Orientation)GetValue(OrientationProperty); }
  14.        set { SetValue(OrientationProperty, value); }
  15.     }
  16.    public static readonly DependencyProperty OrientationProperty =
  17.        DependencyProperty.Register("Orientation", typeof(Orientation), typeof(SkeletonGroup), new PropertyMetadata(Orientation.Vertical));
  18. }
复制代码
四.骨架屏应用案例        
  以下是结合前文《可能是迄今为止最好用的WPF加载动画功能(没有之一)》中的FrameworkElementExtension.IsLoading附加属性实现的骨架屏控制案例,如有疑问可转到该文中查看。
案例一:文字+按钮
5.gif
  1. <Storyboard
  2.     AutoReverse="False"
  3.     RepeatBehavior="Forever">
  4.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  5.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  6.     </DoubleAnimationUsingKeyFrames>
  7. </Storyboard><Storyboard
  8.     AutoReverse="False"
  9.     RepeatBehavior="Forever">
  10.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  11.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  12.     </DoubleAnimationUsingKeyFrames>
  13. </Storyboard>              确定<Path HorizontalAlignment="Center" VerticalAlignment="Center">
  14.    <Path.Fill>
  15.        <RadialGradientBrush>
  16.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  17.            <GradientStop Color="White" Offset="0"/>
  18.        </RadialGradientBrush>
  19.    </Path.Fill>
  20.    <Path.Data>
  21.        <GeometryGroup>
  22.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  23.            <RectangleGeometry Rect="105,0,100,100" />
  24.            <RectangleGeometry Rect="210,40,100,20" />
  25.        </GeometryGroup>
  26.    </Path.Data>
  27. </Path><Grid>
  28.     <Grid.RowDefinitions>
  29.        <RowDefinition Height="*" />
  30.        <RowDefinition Height="*" />
  31.     </Grid.RowDefinitions>
  32.     <Grid.ColumnDefinitions>
  33.        <ColumnDefinition Width="Auto" />
  34.        <ColumnDefinition Width="10" />
  35.        <ColumnDefinition Width="*" />
  36.     </Grid.ColumnDefinitions>
  37.     <Rectangle Grid.Row="0" Grid.Column="0"/>
  38. </Grid><Storyboard
  39.     AutoReverse="False"
  40.     RepeatBehavior="Forever">
  41.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  42.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  43.     </DoubleAnimationUsingKeyFrames>
  44. </Storyboard>      
复制代码
案例二:文字+圆角按钮
6.gif
  1. <Storyboard
  2.     AutoReverse="False"
  3.     RepeatBehavior="Forever">
  4.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  5.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  6.     </DoubleAnimationUsingKeyFrames>
  7. </Storyboard><Storyboard
  8.     AutoReverse="False"
  9.     RepeatBehavior="Forever">
  10.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  11.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  12.     </DoubleAnimationUsingKeyFrames>
  13. </Storyboard>              确定<Path HorizontalAlignment="Center" VerticalAlignment="Center">
  14.    <Path.Fill>
  15.        <RadialGradientBrush>
  16.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  17.            <GradientStop Color="White" Offset="0"/>
  18.        </RadialGradientBrush>
  19.    </Path.Fill>
  20.    <Path.Data>
  21.        <GeometryGroup>
  22.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  23.            <RectangleGeometry Rect="105,0,100,100" />
  24.            <RectangleGeometry Rect="210,40,100,20" />
  25.        </GeometryGroup>
  26.    </Path.Data>
  27. </Path><Grid>
  28.     <Grid.RowDefinitions>
  29.        <RowDefinition Height="*" />
  30.        <RowDefinition Height="*" />
  31.     </Grid.RowDefinitions>
  32.     <Grid.ColumnDefinitions>
  33.        <ColumnDefinition Width="Auto" />
  34.        <ColumnDefinition Width="10" />
  35.        <ColumnDefinition Width="*" />
  36.     </Grid.ColumnDefinitions>
  37.     <Rectangle Grid.Row="0" Grid.Column="0"/>
  38. </Grid><Storyboard
  39.     AutoReverse="False"
  40.     RepeatBehavior="Forever">
  41.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  42.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  43.     </DoubleAnimationUsingKeyFrames>
  44. </Storyboard>      
复制代码
案例三:头像+文字
7.gif
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  16.    <Path.Fill>
  17.        <RadialGradientBrush>
  18.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  19.            <GradientStop Color="White" Offset="0"/>
  20.        </RadialGradientBrush>
  21.    </Path.Fill>
  22.    <Path.Data>
  23.        <GeometryGroup>
  24.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  25.            <RectangleGeometry Rect="105,0,100,100" />
  26.            <RectangleGeometry Rect="210,40,100,20" />
  27.        </GeometryGroup>
  28.    </Path.Data>
  29. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  30.    <Path.Fill>
  31.        <RadialGradientBrush>
  32.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  33.            <GradientStop Color="White" Offset="0"/>
  34.        </RadialGradientBrush>
  35.    </Path.Fill>
  36.    <Path.Data>
  37.        <GeometryGroup>
  38.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  39.            <RectangleGeometry Rect="105,0,100,100" />
  40.            <RectangleGeometry Rect="210,40,100,20" />
  41.        </GeometryGroup>
  42.    </Path.Data>
  43. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  44.    <Path.Fill>
  45.        <RadialGradientBrush>
  46.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  47.            <GradientStop Color="White" Offset="0"/>
  48.        </RadialGradientBrush>
  49.    </Path.Fill>
  50.    <Path.Data>
  51.        <GeometryGroup>
  52.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  53.            <RectangleGeometry Rect="105,0,100,100" />
  54.            <RectangleGeometry Rect="210,40,100,20" />
  55.        </GeometryGroup>
  56.    </Path.Data>
  57. </Path><Grid>
  58.     <Grid.RowDefinitions>
  59.        <RowDefinition Height="*" />
  60.        <RowDefinition Height="*" />
  61.     </Grid.RowDefinitions>
  62.     <Grid.ColumnDefinitions>
  63.        <ColumnDefinition Width="Auto" />
  64.        <ColumnDefinition Width="10" />
  65.        <ColumnDefinition Width="*" />
  66.     </Grid.ColumnDefinitions>
  67.     <Rectangle Grid.Row="0" Grid.Column="0"/>
  68. </Grid><Storyboard
  69.     AutoReverse="False"
  70.     RepeatBehavior="Forever">
  71.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  72.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  73.     </DoubleAnimationUsingKeyFrames>
  74. </Storyboard>   
复制代码
案例四:文字+图片
8.gif
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  16.    <Path.Fill>
  17.        <RadialGradientBrush>
  18.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  19.            <GradientStop Color="White" Offset="0"/>
  20.        </RadialGradientBrush>
  21.    </Path.Fill>
  22.    <Path.Data>
  23.        <GeometryGroup>
  24.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  25.            <RectangleGeometry Rect="105,0,100,100" />
  26.            <RectangleGeometry Rect="210,40,100,20" />
  27.        </GeometryGroup>
  28.    </Path.Data>
  29. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  30.    <Path.Fill>
  31.        <RadialGradientBrush>
  32.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  33.            <GradientStop Color="White" Offset="0"/>
  34.        </RadialGradientBrush>
  35.    </Path.Fill>
  36.    <Path.Data>
  37.        <GeometryGroup>
  38.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  39.            <RectangleGeometry Rect="105,0,100,100" />
  40.            <RectangleGeometry Rect="210,40,100,20" />
  41.        </GeometryGroup>
  42.    </Path.Data>
  43. </Path>        
复制代码
案例五:图片
9.gif
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  16.    <Path.Fill>
  17.        <RadialGradientBrush>
  18.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  19.            <GradientStop Color="White" Offset="0"/>
  20.        </RadialGradientBrush>
  21.    </Path.Fill>
  22.    <Path.Data>
  23.        <GeometryGroup>
  24.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  25.            <RectangleGeometry Rect="105,0,100,100" />
  26.            <RectangleGeometry Rect="210,40,100,20" />
  27.        </GeometryGroup>
  28.    </Path.Data>
  29. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  30.    <Path.Fill>
  31.        <RadialGradientBrush>
  32.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  33.            <GradientStop Color="White" Offset="0"/>
  34.        </RadialGradientBrush>
  35.    </Path.Fill>
  36.    <Path.Data>
  37.        <GeometryGroup>
  38.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  39.            <RectangleGeometry Rect="105,0,100,100" />
  40.            <RectangleGeometry Rect="210,40,100,20" />
  41.        </GeometryGroup>
  42.    </Path.Data>
  43. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  44.    <Path.Fill>
  45.        <RadialGradientBrush>
  46.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  47.            <GradientStop Color="White" Offset="0"/>
  48.        </RadialGradientBrush>
  49.    </Path.Fill>
  50.    <Path.Data>
  51.        <GeometryGroup>
  52.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  53.            <RectangleGeometry Rect="105,0,100,100" />
  54.            <RectangleGeometry Rect="210,40,100,20" />
  55.        </GeometryGroup>
  56.    </Path.Data>
  57. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  58.    <Path.Fill>
  59.        <RadialGradientBrush>
  60.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  61.            <GradientStop Color="White" Offset="0"/>
  62.        </RadialGradientBrush>
  63.    </Path.Fill>
  64.    <Path.Data>
  65.        <GeometryGroup>
  66.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  67.            <RectangleGeometry Rect="105,0,100,100" />
  68.            <RectangleGeometry Rect="210,40,100,20" />
  69.        </GeometryGroup>
  70.    </Path.Data>
  71. </Path>   
复制代码
案例六:图片+文字
10.gif
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  16.    <Path.Fill>
  17.        <RadialGradientBrush>
  18.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  19.            <GradientStop Color="White" Offset="0"/>
  20.        </RadialGradientBrush>
  21.    </Path.Fill>
  22.    <Path.Data>
  23.        <GeometryGroup>
  24.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  25.            <RectangleGeometry Rect="105,0,100,100" />
  26.            <RectangleGeometry Rect="210,40,100,20" />
  27.        </GeometryGroup>
  28.    </Path.Data>
  29. </Path><Storyboard
  30.     AutoReverse="False"
  31.     RepeatBehavior="Forever">
  32.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  33.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  34.     </DoubleAnimationUsingKeyFrames>
  35. </Storyboard><Storyboard
  36.     AutoReverse="False"
  37.     RepeatBehavior="Forever">
  38.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  39.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  40.     </DoubleAnimationUsingKeyFrames>
  41. </Storyboard><Storyboard
  42.     AutoReverse="False"
  43.     RepeatBehavior="Forever">
  44.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  45.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  46.     </DoubleAnimationUsingKeyFrames>
  47. </Storyboard>      
复制代码
案例七:无限嵌套
11.gif
  1. <Path HorizontalAlignment="Center" VerticalAlignment="Center">
  2.    <Path.Fill>
  3.        <RadialGradientBrush>
  4.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  5.            <GradientStop Color="White" Offset="0"/>
  6.        </RadialGradientBrush>
  7.    </Path.Fill>
  8.    <Path.Data>
  9.        <GeometryGroup>
  10.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  11.            <RectangleGeometry Rect="105,0,100,100" />
  12.            <RectangleGeometry Rect="210,40,100,20" />
  13.        </GeometryGroup>
  14.    </Path.Data>
  15. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  16.    <Path.Fill>
  17.        <RadialGradientBrush>
  18.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  19.            <GradientStop Color="White" Offset="0"/>
  20.        </RadialGradientBrush>
  21.    </Path.Fill>
  22.    <Path.Data>
  23.        <GeometryGroup>
  24.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  25.            <RectangleGeometry Rect="105,0,100,100" />
  26.            <RectangleGeometry Rect="210,40,100,20" />
  27.        </GeometryGroup>
  28.    </Path.Data>
  29. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  30.    <Path.Fill>
  31.        <RadialGradientBrush>
  32.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  33.            <GradientStop Color="White" Offset="0"/>
  34.        </RadialGradientBrush>
  35.    </Path.Fill>
  36.    <Path.Data>
  37.        <GeometryGroup>
  38.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  39.            <RectangleGeometry Rect="105,0,100,100" />
  40.            <RectangleGeometry Rect="210,40,100,20" />
  41.        </GeometryGroup>
  42.    </Path.Data>
  43. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  44.    <Path.Fill>
  45.        <RadialGradientBrush>
  46.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  47.            <GradientStop Color="White" Offset="0"/>
  48.        </RadialGradientBrush>
  49.    </Path.Fill>
  50.    <Path.Data>
  51.        <GeometryGroup>
  52.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  53.            <RectangleGeometry Rect="105,0,100,100" />
  54.            <RectangleGeometry Rect="210,40,100,20" />
  55.        </GeometryGroup>
  56.    </Path.Data>
  57. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  58.    <Path.Fill>
  59.        <RadialGradientBrush>
  60.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  61.            <GradientStop Color="White" Offset="0"/>
  62.        </RadialGradientBrush>
  63.    </Path.Fill>
  64.    <Path.Data>
  65.        <GeometryGroup>
  66.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  67.            <RectangleGeometry Rect="105,0,100,100" />
  68.            <RectangleGeometry Rect="210,40,100,20" />
  69.        </GeometryGroup>
  70.    </Path.Data>
  71. </Path><Path HorizontalAlignment="Center" VerticalAlignment="Center">
  72.    <Path.Fill>
  73.        <RadialGradientBrush>
  74.            <GradientStop Color="#FFBBBBBB" Offset="1"/>
  75.            <GradientStop Color="White" Offset="0"/>
  76.        </RadialGradientBrush>
  77.    </Path.Fill>
  78.    <Path.Data>
  79.        <GeometryGroup>
  80.            <RectangleGeometry Rect="0,0,100,100" RadiusX="50" RadiusY="50"/>
  81.            <RectangleGeometry Rect="105,0,100,100" />
  82.            <RectangleGeometry Rect="210,40,100,20" />
  83.        </GeometryGroup>
  84.    </Path.Data>
  85. </Path><Storyboard
  86.     AutoReverse="False"
  87.     RepeatBehavior="Forever">
  88.     <DoubleAnimationUsingKeyFrames Storyboard.TargetName="path" Storyboard.TargetProperty="(Shape.Fill).(Brush.RelativeTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  89.        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6" />
  90.     </DoubleAnimationUsingKeyFrames>
  91. </Storyboard>           
复制代码
 
 ---------完结---------- 
技术赋能,共创未来
  我们是一支深耕WPF及Avalonia十余年的开发团队,专注于为企业和开发者提供高性能桌面应用解决方案,目前已经为二十多家企业提供过服务,无论您是哪种需求,我们都可以用我们丰富的经验助力您的业务高效落地。如果您有相关需求,请与我们联系。
 
联系方式QQ/VX:446522563手机号:17898179019
 
技术交流
QQ群:661224882
12.png

 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册