这篇文章介绍离散式关键帧,并使用它做些有趣的动画。

1. 什么是离散式关键帧

以DoubleAnimationUsingKeyFrames为例,它支持四种Double的关键帧,其中EasingDoubleKeyFrame、LinearDoubleKeyFrame和SplineDoubleKeyFrame可以归类为连续式关键帧,而DiscreteDoubleKeyFrame则是离散式关键帧。

DoubleAnimationUsingKeyFrames包含一个关键帧的集合,动画开始后,每当达到某个关键帧指定的Time,动画的值也会同时到达这个关键帧指定的Value。下面这段XAML介绍了一个典型的LinearDoubleKeyFrame的用法:

<StackPanel>
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
<LinearDoubleKeyFrame Value="1.2" KeyTime="0:0:4"/>
<LinearDoubleKeyFrame Value="2" KeyTime="0:0:5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</StackPanel.Resources>
</StackPanel>

对于连续式的关键帧,两个关键帧之间会进行插值,以上面的XAML为例,当动画运行到4.5秒的时候,DobuleAnimationUsingKeyFrames会根据第二和第三个LinearDoubleKeyFrame的值计算出1.6作为内插的值赋予目标属性ScaleY。EasingDoubleKeyFrame和SplineDoubleKeyFrame也是相同的原理,只是它们的插值计算方式复杂一些。

而离散式关键帧不同,它用在不能插值的数据类型, 例如True/False、Visible/Collapsed这些数据类型,它们之间没有过渡,只能用离散的方式设置值。一段典型的DiscreteObjectKeyFrame示例如下:

<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalRoot" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>

2. 了解下电影的原理

在电影里,一幅静止的图像被称作一“格”(Frame),只要达到每秒24格,人们的眼睛就会被欺骗,以为看到的是运动的画面。人的双眼及其数据传输系统每秒可以识别10-12格画面,大脑的视觉处理中心会将每格画面保留1/15秒。如果在前一格画面尚且保留的1/15秒内大脑又收到一幅新的画面,那么就产生了画面在连续运动的感觉,这是电影得以实现的认知学基础。

3. 用DiscreteDoubleKeyFrame播放动画

DiscreteObjectKeyFrame是最常用的离散式关键帧,UWP还提供了其它三种离散式关键帧:DiscreteColorKeyFrame、DiscreteDoubleKeyFrame和DiscretePointKeyFrame。如果不是追求动画效果,日常工作中DiscreteDoubleKeyFrame基本上没什么作为(在Github上DiscreteObjectKeyFrame有132K的搜索结果,DiscreteDoubleKeyFrame只有17K)。但只要了解了电影的原理,配合设计师的话DiscreteDoubleKeyFrame也可以大展拳脚。

<ScrollViewer Background="Transparent"
VerticalScrollBarVisibility="Disabled"
HorizontalScrollBarVisibility="Disabled">
<Grid Width="2900">
<Image Stretch="None"
AutomationProperties.AccessibilityView="Raw"
Source="/Assets/Images/heart.png"
Height="100"
Loaded="OnHeartLoaded"
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<CompositeTransform />
</Image.RenderTransform>
</Image>
</Grid>
</ScrollViewer>

上面的XAML是一个Like按钮(模仿某个不存在的网站)的ControlTemplate,ScrollViewer用于裁剪超出范围的内容,里面包含一张由29张100 X 100的图片拼接而成的长图片:

private Storyboard _checkStoryboard;
private CompositeTransform _heartTransform; private void OnHeartLoaded(object sender, RoutedEventArgs e)
{
_heartTransform = (sender as Image).RenderTransform as CompositeTransform;
_checkStoryboard = new Storyboard(); var keyFrames = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(keyFrames, _heartTransform);
Storyboard.SetTargetProperty(keyFrames, nameof(CompositeTransform.TranslateX));
TimeSpan start = TimeSpan.Zero;
for (var i = 0; i < 28; i++)
{
var keyFrame = new DiscreteDoubleKeyFrame
{
KeyTime = TimeSpan.FromSeconds((i + 1d) / 28d),
Value = -(i + 1) * 100
};
keyFrames.KeyFrames.Add(keyFrame);
} _checkStoryboard.Children.Add(keyFrames); _checkStoryboard.FillBehavior = FillBehavior.HoldEnd;
} private void OnChecked(object sender, RoutedEventArgs e)
{
_checkStoryboard.Begin();
}

在CodeBehind的OnChecked函数中启动一个Storybord,使用DiscreteDoubleKeyFrame让Image在一秒内向左平移100像素,这样就达到了播放动画的效果:

换一张Demo试试,这次使用了12帧每秒,看上去就有点卡顿:

4. 结语

这篇文章的代码在WPF和UWP上的实现几乎一样,有兴趣的话也可以在WPF上试试。

LikeButton的动画抄自Codepen,在CSS中离散动画实现起来很简洁:

.heart {
width: 100px;
height: 100px;
background: url("https://cssanimation.rocks/images/posts/steps/heart.png") no-repeat;
background-position: 0 0;
cursor: pointer;
transition: background-position 1s steps(28);
transition-duration: 0s; &.is-active {
transition-duration: 1s;
background-position: -2800px 0;
}
}

更多关于steps的内容可参考下面这篇文章

CSS3 animation属性中的steps功能符深入介绍

5. 参考

情节提要动画 - UWP applications Microsoft Docs

关键帧动画以及缓动函数动画 - UWP applications Microsoft Docs

DiscreteDoubleKeyFrame Class (Windows.UI.Xaml.Media.Animation) - Windows UWP applications Microsoft Docs

6. 源码

design_and_animation_lab

[UWP]使用离散式关键帧播放动画的更多相关文章

  1. [UWP]使用SpringAnimation创建有趣的动画

    1. 什么是自然动画 最近用弹簧动画(SpringAnimation)做了两个番茄钟,关于弹簧动画官方文档已经介绍得够详细了,这篇文章就摘录一些官方文档核心内容. 在传统UI中,关键帧动画(KeyFr ...

  2. Android PowerImageView实现,可以播放动画的强大ImageView

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11100315 我个人是比较喜欢逛贴吧的,贴吧里总是会有很多搞笑的动态图片,经常看一 ...

  3. Windows10 UWP开发 - 响应式设计

      Windows10 UWP开发 - 响应式设计 本篇随笔与大家简单讨论一下在开发适配不同分辨率.宽高比的Windows10 Universal App布局时的可行方式与小技巧.经验均从实践中总结, ...

  4. Android开发教程AnimationDrawable逐帧播放动画

    下面我们一起来看篇Android开发AnimationDrawable控制逐帧播放动画实现过程,希望文章对各位朋友带不一些帮助. 当我们点击按钮时,该图片会不停的旋转,当再次点击按钮时,会停止在当前的 ...

  5. iOS控件——UIView与UIImageView播放动画的实现方法

    1.UIView //初始状态 [UIView animateWithDuration:(int) animations:^{ //最终状态 }completion:^(BOOL finished){ ...

  6. iOS 仪表式数字跳动动画-b

    前几天搞了 双曲线波浪动画(http://www.jianshu.com/p/7db295fd38eb)和环形倒计时动画(http://www.jianshu.com/p/d1d16dff33c9)而 ...

  7. qt程序启动播放动画

    qt程序启动播放动画 编辑删除转载 2016-01-20 10:23:11 标签:qt启动动画 1.播放动画 QAxWidget *flash = , ); //QAxWidget使用的是Active ...

  8. android 监听动画对象后不能播放动画

    采用监听  AnimationListener 发现不能播放动画了. 解决办法: 将动画的启动方式:animation.startnow去掉,改为如下即可 view.startAnimation(an ...

  9. cocos2dx中快速完成一段可播放动画

    版本:cocos2dx 2.2.6 IDE: VS2012 语言:C++98 CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteF ...

随机推荐

  1. 【万字长文】别再报班了,一篇文章带你入门Python

    本文始发于个人公众号:TechFlow,原创不易,求个关注 最近有许多小伙伴后台联系我,说目前想要学习Python,但是没有一份很好的资料入门.一方面的确现在市面上Python的资料过多,导致新手会不 ...

  2. .user.ini 无法修改/删除 怎么办?

    首先 了解chattr命令: Linux chattr命令用于改变文件属性. 这项指令可改变存放在ext2文件系统上的文件或目录属性,这些属性共有以下8种模式: a:让文件或目录仅供附加用途.b:不更 ...

  3. 数学--数论--直角三角形--勾股数---奇偶数列法则 a^2+b^2=c^2

    先说勾股数: 勾股数,又名毕氏三元数 .勾股数就是可以构成一个直角三角形三边的一组正整数.勾股定理:直角三角形两条直角边a.b的平方和等于斜边c的平方(a²+b²=c²) 勾股数规律: 首先是奇数组口 ...

  4. 搜索+简单dp

    前言:即使是简单的递归,在复杂度过高时也可以使用简单的dp. 一般有两种情况,一是利用dp思想求最优子结构进行搜索剪枝,二是利用搜索进行dp数组的填充. 例题一.hdu1978 题目大意:这是一个简单 ...

  5. 在web中使用shiro(会话管理,登出,shiro标签库的使用)

    在shiro的主配置文件中配置,登出的请求经过的过滤器就可以了,在shiro的过滤器中有一个名称为logout的过滤 器专门为我们处理登出请求: 一.shiro会话管理器 shiro中也提供了类似于w ...

  6. 【大数据 Spark】利用电影观看记录数据,进行电影推荐

    利用电影观看记录数据,进行电影推荐. 目录 利用电影观看记录数据,进行电影推荐. 准备 1.任务描述: 2.数据下载 3.部分数据展示 实操 1.设置输入输出路径 2.配置spark 3.读取Rati ...

  7. Boosting算法总结(ada boosting、GBDT、XGBoost)

    把之前学习xgb过程中查找的资料整理分享出来,方便有需要的朋友查看,求大家点赞支持,哈哈哈 作者:tangg, qq:577305810 一.Boosting算法 boosting算法有许多种具体算法 ...

  8. [poj 1743] Musical Theme 后缀数组 or hash

    Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...

  9. CF#358 D. Alyona and Strings DP

    D. Alyona and Strings 题意 给出两个字符串s,t,让找出最长的k个在s,t不相交的公共子串. 思路 看了好几个题解才搞懂. 代码中有注释 代码 #include<bits/ ...

  10. [Vue warn]: Missing required prop: "value"

    tips vue中遇到这个问题 真的是很苦恼 一点一点排查 ,最后发现是因为我在 select的option中写了个默认值 ,所以才报这个错误 注释:去掉默认值那个option 选项就不报错了