本文将从 OpenXML 方面聊 PPT 的动画框架,本文是属于编程方面而不是 PPT 动画制作教程
开始之前,还请掌握一些基础知识,如阅读以下博客
本文不讨论 Slide Master 和 Slide Layout 的动画,关于这两个请参阅 dotnet OpenXML 的 Slide Master 和 Slide Layout 是什么
本文只讨论 Slide 页面里面的动画
元素主序列动画
在 OpenXML 中,如果一个动画是依靠翻页或点击页面进行触发的,那么这些动画有顺序的触发,这部分就是主序列动画,也叫 主动画序列 在 OpenXML 的 PPTX 文件里面的存放大概如下
动画是存放在 Slide 页面里面的 Timing 属性里面,通过 OpenXML SDK 获取方法如下
默认的动画将会放在 NodeType 为 TmingRoot 的 cTn 也就是 CommonTimeNode 里面,获取代码如下
按照约定,页面里面的动画将放在 TmingRoot 的里层,而元素的主序列动画也属于页面里面的动画,因此也就放在 TmingRoot 的里层
如上面代码就是 nodeType="mainSeq"
主序列动画的定义,获取主序列动画的代码如下
接下来讨论的就是放在主序列动画里面的动画的存储方式,以上代码放在 github 和 gitee 欢迎访问
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
获取代码之后,进入 PptxDemo 文件夹
单个主序列动画
放在主序列动画里面的单个动画,创建方式如新建一个 PPT 文件,然后拖入一个形状,点击一下飞入动画。此时的飞入动画就是属于放在主动画序列的一个动画,当然飞入动画在类型上属于进入动画。在 PPT 里面,有 进入动画、强调动画、退出动画等类型
以下是单个飞入动画的主序列动画的 OpenXML 文档的例子
可以看到单个动画放在单个主序列动画的两层 cTn 里面
如上面的内容,大概可以理解存放的方式了,只是在 PPT 里面,有多个 ParallelTimeNode 和 CommonTimeNode 的嵌套。从 mainSeq 也就是 MainSequence 主动画序列以下,获取到的实际的进入动画,是经过了如下路径才能获取
代码的获取方式如下
以上测试文件和测试代码 放在 github 和 gitee 可以通过以下命令获取
除了进入动画之外,还有强调和退出动画,详细请看 dotnet OpenXML 读取 PPT 动画进入退出强调动画类型
主序列顺序动画
新建 PPT 课件,添加一个元素,然后分别设置元素的进入强调和退出动画,然后设置强调和退出动画是从上一项之后开始,如下图
根据上文描述,可以了解到此时元素的进入和强调和退出类型动画都放在主序列动画里面,如下图
进一步简化的代码如下
从以上可以看到,所有的动画都放在主序列动画的 childTnLst 也就是 ChildTimeNodeList 里面的里面,在 NodeType 为 MainSequence 的 CommonTimeNode 里面嵌套一个 p:par
和一个 id 为 3 的 p:cTn
之后,才是各个动画的内容
可以使用如下代码进行获取
以上测试文件和测试代码 放在 github 和 gitee 可以通过以下命令获取
如果不是按照顺序连续播放的,而是按照每次点击进行顺序播放的,也就是每个动画的触发都是鼠标点击的,那么存储方式将会是如下
来对比一下两个的差别吧,如果是单次点击,连续出现三个动画的,那么这三个动画将会被一个 cTn 包含出来,如下面代码,咱使用以 MainSequence 作为最顶层来看
对比简化的单次点击出现单个动画,顺序点击三次,分别出现三个动画的框架,如以下代码
具体差别就在于,如上面代码,如果是单次点击,连续出现三个动画的,那么将会被放在一个 cTn 里面,如上面代码 id 为 3 的 cTn 里面。而如果是单个点击出现单个动画的,动画和动画之间不是连续播放的,那么就放在 MainSequence 的 childTnLst 里面
更多关于主序列进入退出强调动画,请看 dotnet OpenXML 读取 PPT 主序列进入退出强调动画
在了解多个动画的触发顺序和依赖关系之前,咱先继续聊聊单个动画的存储框架
单个动画的存储框架
在本文的一开始就聊到了单个主序列动画,但上文没有给出一个动画的范围,而在经过了主序列顺序动画,似乎可以了解每个独立动画存储的边界以及存储框架方式
假定动画之前没有依赖,单次点击只进行一个动画的,如上文,大的动画存储框架如下代码
以上被注释的 进入动画 部分的实际代码大概如下
也就是单个动画部分内容大概如下
忽略动画实际的内容的代码如下
而通过 id 为 5 的 cTn 可以看到,这个才是实际的动画执行信息,这个 cTn 存放的层级如下
以上测试课件放在 github 和 gitee 可以通过以下命令获取
单个动画内的各个属性以及表示属于什么动画部分,将在下文告诉大家
但如果动画是有依赖的,如单次点击,然后连续出现三个动画的课件,如上文,存储的框架如下
展开里面的进入动画,其内容大概如下
也就是说进入动画的内容大概如下
忽略动画实际的内容的代码如下
对比一下代码可以看到,如单次点击,然后连续出现三个动画的课件,单个动画的距离 MainSequence 的层级要比每次点击只有一个动画的课件少了一层 par -> cTn -> childTnLst
的嵌套
原因是在外层将单次点击,然后连续出现三个动画的三个动画当成了一个主序列的动画。也就是说在 PPT 的存储里面,认为的框架如下
因此就比每次点击只有一个动画的课件少了一层。通过以上即可了解到,读取时,就应该采用判断组合的方法,将 MainSequence 里面的 childTnLst 的每一个 par 当成独立的动画。只是有一些独立的动画是组合动画,组合动画里面可以再包含多个动画
动画的触发顺序
回到动画的触发顺序,依然是在主序列上,如果是单次点击同时出现三个动画,也就是说第一个动画是点击触发,另外两个动画是设置 从上一项开始 的动画
如上图,三个动画分别是向下动画、不饱和动画、旋转动画。为什么这次不使用进入强调退出做例子?原因是同时进行的动画,如果设置了同时进行,不好调试
从文档的代码可以看到,动画如下
展开各个动画的内容如下
从以上代码可以看到,设置动画在从上一项开始的,和从上一项开始之后的动画的存储框架是不相同的,下面对比一下两个设置方式的代码
可以看到,如果设置的动画是同时出现的,将会被放入到 MainSequence 的里面两层,而如果是设置顺序出现的动画,将会被放入 MainSequence 的里面一层
以上测试课件放在 github 和 gitee 可以通过以下命令获取
主序列动画框架
主序列动画的顺序上,可以分为以下不同的方式
-
动画之间是相互不影响,每个动画通过点击触发的方式,如 三次点击触发三次动画
-
动画之间相互影响,动画连续触发,在一个动画执行完成之后,再继续下一个动画,如 单次点击连续触发三个动画
-
动画之间相互影响,动画同时触发,在点击之后所有动画同时进行,如 单次点击同时触发三个动画
更复杂的部分是以上三个组合的复杂情况,咱先忽略复杂的组合情况,先聊以上的方式
下面是三个方式的框架对比
可以看到不同的动画触发方式将会影响动画的存储框架
触发序列框架
在 PPT 里面,除了主序列动画之后,还有触发序列。触发序列是由点击某个元素进行触发的动画
触发序列和主序列如命名,在 TmingRoot 之下的一层,和主序列相同的一层里面,采用 InteractiveSequence 标识。在 OpenXML 里面的文档内容大概如下
在 InteractiveSequence 之下的元素存储框架和主序列完全相同,只是在触发序列里面的各个动画会采用 stCondLst
里面的 TargetElement 来决定是由哪个元素点击触发的动画
如以下的 OpenXML 内容
以上的逻辑表示了采用 p:spTgt spid="3"
的元素来触发 p:spTgt spid="4"
的元素动画
获取触发序列的逻辑如下
在触发序列里面,获取触发动画元素的方法如下
以上拿到的 shape 就是用来触发动画的元素
接下来获取具体的动画逻辑和主序列相同
以上测试课件和代码放在 github 和 gitee 可以通过以下命令获取
对于触发序列,如果是通过相同的一个动画触发的多个动画,那么多个动画的存放是放在相同的触发序列之下。和主序列的不同在于,在 PPT 可以有多个触发序列。每个触发序列表示有一个元素触发的动画。每个触发序列里面,触发动画的元素触发的动画允许有多个
如多次点击相同的一个元素来分别触发三个元素的淡入动画的 OpenXML 文档
以上文档就是点击 Id 是 3 的元素分别触发 Id 是 4 5 6 元素的淡入动画。对元素 Id 是 4 5 6 的元素的 NodeType 是 ClickEffect 因此是多次点击 Id 是 3 的元素进行分别触发
本文的属性是依靠 dotnet OpenXML 解压缩文档为文件夹工具 工具协助测试的,这个工具是开源免费的工具,欢迎使用
更多请看 Office 使用 OpenXML SDK 解析文档博客目录
原文链接: http://blog.lindexi.com/post/dotnet-OpenXML-PPT-%E5%8A%A8%E7%94%BB%E6%A1%86%E6%9E%B6%E5%85%A5%E9%97%A8
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。