1. 运行效果

使用GetAlphaMask和ContainerVisual制作长阴影(Long Shadow) 这篇文章里我介绍了一个包含长阴影的番茄钟,这个番茄钟在状态切换时用到了翻转动画,效果如上所示,还用到了弹簧动画,可以看到翻转后有点回弹。本来打算自己这个动画效果写的,但火火已经写好了这个FlipSide控件,Github地址在这里,这篇文章就介绍下这个控件的部分原理。

2. TransformMatrix

Visual的 TransformMatrix 属性是一个 Matrix4x4 的struct,它是应用于元素的转换矩阵,可以进行动画处理。它的默认值如下:

这时候动画效果如下:

要使Visual可以正确旋转需要按以下方式处理:

private void UpdateTransformMatrix(FrameworkElement element)
{
var host = ElementCompositionPreview.GetElementVisual(element);
var size = element.RenderSize.ToVector2();
if (size.X == 0 || size.Y == 0) return;
var n = -1f / size.X; Matrix4x4 perspective = new Matrix4x4(
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, n,
0.0f, 0.0f, 0.0f, 1.0f); host.TransformMatrix =
Matrix4x4.CreateTranslation(-size.X / 2, -size.Y / 2, 0f) *
perspective *
Matrix4x4.CreateTranslation(size.X / 2, size.Y / 2, 0f);
}

讲真我也不明白为什么要这么写,只知道是从微软的 例子 里抄的。每当SizeChanged事件发生时都需要调用这个函数重新设置TransformMatrix。

3. RotationAngleInDegrees

Visual包含两个相似的属性,RotationAngleInDegreesRotationAngle,它们的定义如下:

//
// 摘要:
// 视觉对象的旋转角度(以度为单位)。 可动画处理。
//
// 返回结果:
// The rotation angle of the visual in degrees.
public float RotationAngleInDegrees { get; set; }
//
// 摘要:
// 视觉对象的旋转角度(以弧度为单位)。 可动画处理。
//
// 返回结果:
// The rotation angle in radians of the visual.
public float RotationAngle { get; set; }

这两个属性都用于控制Visua围绕着RotationAxis和CenterPoint旋转。在FlipSide这个控件里RotationAngleInDegrees比较适用:

float f1 = 0f, f2 = 0f;
if (IsFlipped)
{
f1 = 180f;
f2 = 360f;
VisualStateManager.GoToState(this, "Slide2", false);
}
else
{
f1 = 0f;
f2 = 180f;
VisualStateManager.GoToState(this, "Slide1", false);
}
if (springAnimation1 != null && springAnimation2 != null)
{
springAnimation1.FinalValue = f1;
springAnimation2.FinalValue = f2;
s1Visual.StartAnimation("RotationAngleInDegrees", springAnimation1);
s2Visual.StartAnimation("RotationAngleInDegrees", springAnimation2);
}

这段代码用到了SpringAnimatin,所以有弹一下的效果。

4. RotationAxis

RotationAxis 用于指定Visual旋转的轴。FlipSide可以通过设置RotationAxis改变翻转的角度,例如火火的Demo里使用根据鼠标改变RotationAxis:

private void OnFlipSidePointerReleased(object sender, PointerRoutedEventArgs e)
{
var position = e.GetCurrentPoint(_FlipSide).Position;
var v2 = (position.ToVector2() - _FlipSide.RenderSize.ToVector2() / 2);
_FlipSide.Axis = new Vector2(-v2.Y, v2.X);
}

5. ExpressionAnimation

<controls:FlipSide x:Name="FlipSide" IsFlipped="True">
<controls:FlipSide.Side1>
<Grid Background="#FFE87A69" x:Name="InworkElement" CornerRadius="1"> </Grid>
</controls:FlipSide.Side1>
<controls:FlipSide.Side2>
<Grid Background="#FF5271c2" x:Name="BreakElement" CornerRadius="1"> </Grid>
</controls:FlipSide.Side2>
</controls:FlipSide>

上面XAML为FlipSide的调用代码,它将Side1和Side2(这个命名超让高达迷兴奋)作为内容显示在UI上,当IsFlipped为False时显示Side1的内容,当IsFlipped为True时代表翻转过去,此时显示Side2的内容。在翻转动画的过程中,何时隐藏Side1并显示Side2是个麻烦事。幸好UWP有强大的表达式动画(ExpressionAnimation),FlipSide只用了下面几句代码处理这个问题:

s1Visual = ElementCompositionPreview.GetElementVisual(Side1Content);
s2Visual = ElementCompositionPreview.GetElementVisual(Side2Content); var opacity1Animation = compositor.CreateExpressionAnimation("this.Target.RotationAngleInDegrees > 90 ? 0f : 1f");
var opacity2Animation = compositor.CreateExpressionAnimation("(this.Target.RotationAngleInDegrees - 180) > 90 ? 1f : 0f"); s1Visual.StartAnimation("Opacity", opacity1Animation);
s2Visual.StartAnimation("Opacity", opacity2Animation);

这段代码的意思是当Side1的RotationAngleInDegrees大于90度时隐藏,否则显示;Side2则相反。其中,表达式中的this.Target表示使用这个表达式动画的Vsual。

表达式动画的话题很大,这篇文章就割爱了,可以参考下面给出的链接了解更多内容:

基于关系的动画 - Windows UWP applications Microsoft Docs

【Win 10 应用开发】UI Composition 札记(七):基于表达式的动画 - 东邪独孤 - 博客园

6. 结语

感谢火火提供了这个控件,让我可以省下了不少功夫。其实我对TransformMatrix真的不理解,所以这部分只是用,没办法详细介绍。而且我以前对UI里使用3D不感兴趣,所以这方面真的没法写更多内容。期待火火为这方面补充一些博客。

7. 参考

基于关系的动画 - Windows UWP applications Microsoft Docs

【Win 10 应用开发】UI Composition 札记(七):基于表达式的动画 - 东邪独孤 - 博客园

ExpressionAnimation Class (Windows.UI.Composition) - Windows UWP applications Microsoft Docs

Visual.TransformMatrix Property (Windows.UI.Composition) - Windows UWP applications Microsoft Docs

合成视觉对象 - Windows UWP applications Microsoft Docs

XAML 属性动画 - Windows UWP applications Microsoft Docs

8. 源码

cnbluefire_FlipSide

[UWP]使用CompositionAPI的翻转动画的更多相关文章

  1. CSS图片翻转动画技术详解

    因为不断有人问我,现在我补充一下:IE是支持这种技术的!尽管会很麻烦.需要做的是旋转front和back元素,而不是旋转整个容器元素.如果你使用的是最新版的IE,可以忽略这一节.IE10+是支持的,I ...

  2. 两个activity的3D翻转动画.md

    一.业务需求 这里在公司项目设计时,用到了一个小的需求,就是点击一个按钮然后整个activity的页面进行3d翻转; 二.设计思路 由于是2个activity的之间的翻转动画,就意味着前90度是A页面 ...

  3. CSS3图片翻转动画技术详解

    CSS动画非常的有趣:这种技术的美就在于,通过使用很多简单的属性,你能创建出漂亮的消隐效果.其中代表性的一种就是CSS图片翻转效果,能让你看到一张卡片的正反两面上的内容.本文就是要用最简单的方法向大家 ...

  4. 解决web翻转动画闪屏

    首先确保backface-visibility: hidden.这样做可以解决大部分闪屏的情况. 然后需要特别注意的是谷歌的浏览器,不管是桌面端还是移动端,在翻转的过程中在该元素上绘制其他元素也会导致 ...

  5. Expression Blend 的点滴(2)--利用可视化状态创建神奇翻转动画

    原文:Expression Blend 的点滴(2)--利用可视化状态创建神奇翻转动画 首先,来看下实现后的效果: 关于VisulaState VisualState 指定控件处于特定状态时的外观.例 ...

  6. uwp - 控件精确移动动画

    原文:uwp - 控件精确移动动画 先看效果图: 一共有8个GRID,黄色的负责移动,其他7个负责定位.新建一个页面page,替换默认代码: <UserControl.Resources> ...

  7. 使用CSS3 BACKFACE-VISIBILITY属性制作翻转动画效果

    摘要: 通过backface-visibility:hidden;属性,我们可以使一个元素在翻转之后消失,这是可以使用另一个元素放在它的背面,从而制作出一种元素翻转之后出现另一个元素的效果. ... ...

  8. iOS的view翻转动画实现--代码老,供参考

    新建一个view-based模板工程,在ViewController文件中添加下面的代码,即可实现翻转效果: - (void)viewDidLoad { [super viewDidLoad]; // ...

  9. WPF翻转动画

    在WPF中要翻转对象,估计是得用三维变换,所以我用到了AxisAngleRotation3D,让图形绕着Z轴来旋转. 先看看效果. 是的,就是这样的效果,在XAML中,由于涉及三维图形,我先做了两个用 ...

随机推荐

  1. Windows搭建SVN服务器

    安装 1.下载地址:https://www.visualsvn.com/files/VisualSVN-Server-4.0.3-x64.msi 2.开始安装: 3.安装配置: 4.Next直到完成 ...

  2. salt-api 配置使用

    salt-api 安装  配置源 (系统环境s示例是centos6) epel 源 rpm -Uvh https://mirrors.tuna.tsinghua.edu.cn/epel/6/i386/ ...

  3. MyBatis拦截器自定义分页插件实现

    MyBaits是一个开源的优秀的持久层框架,SQL语句与代码分离,面向配置的编程,良好支持复杂数据映射,动态SQL;MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyB ...

  4. 【元学习】Meta Learning 介绍

    目录 元学习(Meta-learning) 元学习被用在了哪些地方? Few-Shot Learning(小样本学习) 最近的元学习方法如何工作 Model-Agnostic Meta-Learnin ...

  5. Django跨域问题(CORS错误)

    Django跨域问题(CORS错误) 一.出现跨域问题(cors错误)的原因 通常情况下,A网页访问B服务器资源时,不满足以下三个条件其一就是跨域访问 协议不同 端口不同 主机不同 二.Django解 ...

  6. Qt5教程: (8) 标准对话框和文件对话框

    1. about对话框 包含头文件 #include <QMessageBox> 添加菜单项 QAction *p3 = pDialog->addAction("关于&qu ...

  7. PowerSploit-CodeExecution(代码执行)脚本渗透实战

    首先介绍一下国外大牛制作的Powershell渗透工具PowerSploit,上面有很多powershell攻击脚本,它们主要被用来渗透中的信息侦察.权限提升.权限维持. 项目地址:https://g ...

  8. php数组怎么根据其中的一个值进行排序?解决方法

    有一个数组如下 我想对其进行一个排序,按照其“sort”的值的大小进行排序,3->4->7. 解决方法如下: 1.首先介绍php的两个方法 方法一:array_column() 返回输入数 ...

  9. .NET进阶篇04-Serialize序列化、加密解密

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂这篇很轻松,没有什么费脑子的,所以解析较少,代码较多,为数不多的拿来即用篇整个章节分布请移步 内容目录 一.概述二.序列化1.二进制文件2.XML ...

  10. mysql数据库limit分页,排序操作

    看到网上很多朋友在问,limit分页之后按照字段属性排序的问题,在这里分享一下我的用法: 1.网上答案: 每页显示5个,显示第三页信息,按照年龄从小到大排序 select * from student ...