本來想要先來改進之前的動畫呈現,不過在這之前還是先整理一下描述投影片中timing的結構,因為這個結構有點複雜,需要想好怎麼整理出最終的物件架構。
Office OpenXML中,把投影片中所有會發生的動作,都匯集在一個在p:timing的tag中。以之前做過的動畫效果呈現的投影片範例,他的XML長這樣:
<p:timing>
<p:tnLst>
<p:par>
<p:cTn id="1" dur="indefinite" restart="never" nodeType="tmRoot" xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main">
<p:childTnLst>
<p:seq concurrent="1" nextAc="seek">
<p:cTn id="2" dur="indefinite" nodeType="mainSeq">
<p:childTnLst>
<p:par>
<p:cTn id="3" fill="hold">
<p:stCondLst>
<p:cond delay="indefinite" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="4" fill="hold">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="5" presetID="63" presetClass="path" presetSubtype="0" accel="50000" decel="50000" fill="hold" nodeType="clickEffect">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:animMotion origin="layout" path="M 0 0 L 0.25 0 E" pathEditMode="relative" ptsTypes="">
<p:cBhvr>
<p:cTn id="6" dur="2000" fill="hold" />
<p:tgtEl>
<p:spTgt spid="5">
<p:txEl>
<p:pRg st="0" end="0" />
</p:txEl>
</p:spTgt>
</p:tgtEl>
<p:attrNameLst>
<p:attrName>ppt_x</p:attrName>
<p:attrName>ppt_y</p:attrName>
</p:attrNameLst>
</p:cBhvr>
</p:animMotion>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
<p:par>
<p:cTn id="7" fill="hold">
<p:stCondLst>
<p:cond delay="indefinite" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="8" fill="hold">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="9" presetID="42" presetClass="path" presetSubtype="0" accel="50000" decel="50000" fill="hold" nodeType="clickEffect">
<p:stCondLst>
<p:cond delay="0" />
</p:stCondLst>
<p:childTnLst>
<p:animMotion origin="layout" path="M 0 0 L 0 0.33322 E" pathEditMode="relative" ptsTypes="">
<p:cBhvr>
<p:cTn id="10" dur="2000" fill="hold" />
<p:tgtEl>
<p:spTgt spid="6">
<p:txEl>
<p:pRg st="0" end="0" />
</p:txEl>
</p:spTgt>
</p:tgtEl>
<p:attrNameLst>
<p:attrName>ppt_x</p:attrName>
<p:attrName>ppt_y</p:attrName>
</p:attrNameLst>
</p:cBhvr>
</p:animMotion>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
<p:prevCondLst>
<p:cond evt="onPrev" delay="0">
<p:tgtEl>
<p:sldTgt />
</p:tgtEl>
</p:cond>
</p:prevCondLst>
<p:nextCondLst>
<p:cond evt="onNext" delay="0">
<p:tgtEl>
<p:sldTgt />
</p:tgtEl>
</p:cond>
</p:nextCondLst>
</p:seq>
</p:childTnLst>
</p:cTn>
</p:par>
</p:tnLst>
</p:timing>
落落長...
不過大致可以看出,實際定義動作的p:animMotion這個tag,藏在最深處...當然用人眼來剖析很容易,但是要用程式來剖析,並且最後可以實作出該有的動作及觸發的方式,會需要知道這個結構的各個部件的意義。
回頭對照一下ECMA-376底下相關的定義,可以發現雖然在看這些tag的時候不太明顯,但是他們還是一個node tree的結構。從p:tnLst開始看一下:
分析過後,再回頭去看p:timing底下的xml,就大致上知道他們在描述什麼。以上述的例子來看:
(不過有些地方xsd的定義跟規格中的說明好像不是很一致,也許我的理解有問題,反正還是先用實際的PowerPoint檔及在PowerPoint中展現的效果來做XD)
之前是使用一個按鈕對應一個動畫效果的動作,這只是為了確認動畫效果怎麼實作。要符合p:timing的話,改成「上一步」/「下一步」兩個按鈕會是更好的做法。
另外在資料處理上,cTn是p:par/p:seq/p:excl一定會有的子元素,考慮把結構在壓扁一點的話,其實可以移作p:par/p:seq/p:excl的屬性。
明天先處理一下資料的調整,先手動建立timing的資料,然後讓動畫效果還是可以依照「上一步」/「下一步」的操作執行。至於資料的剖析,還是等到更後面再進行。