Impress/API/Animations

From Apache OpenOffice Wiki
Jump to: navigation, search

Working with animations in impress

See also working_with_documents

The animation model in impress

There are two types of animations in impress. The first are the slide animations. Slide animations describe the transition from the current to the next slide (for example a slide can just apear, or maybe fade in or move in from the bottom). The other kind of animations are shape animations.

The animations in impress are based on the SMIL language.

Timing root

Each slide in a presentation supports the interface com.sun.star.animations.XAnimationNodeSupplier. It's getAnimationNode() method returns a com.sun.star.animations.XAnimationNode element that is a parallel time container.

This timing root element should contain one sequence time container element which is the main sequence for shape effects and zero or more sequence time container elements that define interactive sequences for shapes that contain interaction animations.

The animation root element may further contain a parallel time container element that defines the slide animation.

 oDoc = thiscomponent.DrawPages(0)
 oPage = oDoc.DrawPages(0)
 oMainSequence = oPage.AnimationNode
 
 oEnum = oMainSequence.createEnumeration()
 While( oEnum.hasModeElements() )
   oChild = oEnum.nextElement()
   ' now do somthing with a timing root child
 Wend

Slide animation

A slide animation element must be a parallel time container element at the first position inside the animation root element. Its begin attribute must have a com.sun.star.animations.Event struct which source attribute is the parent com.sun.star.presentation.DrawPage. Its Trigger attribute must be com.sun.star.animations.EventTrigger.ON_BEGIN.

The slide animation element should then contain one or more animation elements like com.sun.star.animations.XTransitionFilter.

<draw:page draw:id="id1">
 <anim:par presentation:node-type="timing-root">
  <anim:par smil:begin="id1.begin">
   <anim:transitionFilter smil:dur="2s" smil:targetElement="id1" smil:type="slideWipe" smil:subtype="fromBottom" smil:direction="reverse"/>
  </anim:par>
 </anim:par>
</draw:page>

Main sequence

The main sequence element is a is a sequential time container which contains the effects that should start after the slide has executed its initial transition. Since this is a sequential container, its child nodes are executed one after each other.

If a child elements begin attribute has the value com.sun.star.animation.Event with the Trigger set to com.sun.star.animations.EventTrigger.ON_NEXT, then the execution is stalled until the user advances the presentation by a mouse or key interaction.

The first level of child elements in the main sequence should be parallel time container elements that group animation elements that are started with the same user interaction. The second level of child nodes should be parallel time container elements that group animations elements that start at the same time. The third level of child nodes should be parallel time container elements that group the animation elements for a single effect.

Example: The following example shows the xml representation of a main sequence with the effects A, B, C and D. Effect A is started on user interaction, effect B is started simultaneously with A. Effect C is started 4 seconds after the effects A and B. Effect D is started on the next user interaction:

<anim:par> <!-- timing root-->
 <anim:seq> <!-- main sequence-->
  <anim:par smil:begin="next">
   <!-- first user interaction -->
   <anim:par smil:begin="0s" smil:dur="4s">
    <!-- first group of effects to execute -->
    <anim:par> <!-- effect a -->
     <!-- nodes for effect a-->
    </anim:par>
    <anim:par> <!-- effect b -->
     <!-- nodes for effect b-->
    </anim:par>
   </anim:par>
   <anim:par smil:begin="4s">
    <!-- second group of effects to execute -->
    <anim:par> <!-- effect c -->
     <!-- nodes for effect c-->
    </anim:par>
   </anim:par>
  </anim:par>
  <anim:par>
   <!-- second user interaction-->
   <anim:par smil:begin="next">
    <!-- first group of effects to execute -->
    <anim:par> <!-- effect d -->
     <!--- nodes for effect d-->
    </anim:par>
   </anim:par>
  </anim:par>
 </anim:seq>
</anim:par>

Interactive Sequence

An interactive sequence is a <anim:seq> element that should have the same structure as a main sequence. The only difference is that the <anim:par> element in the first level has a smil:begin attribute with a value like [shape-id].click, where [shape-id] identifies a drawing shapes by its draw:id attribute. These animation elements are triggered when the user interacts with the element defined by [shape-id].

Example

The following basic example looks at the main sequence of the first page and displays is in a linear fashion. Please note that the string returned from getEffectClass() and getEffectId() is only for user interface purpose. The effect itself is always described with the child elements of each effect node.

Sub Main
	oMainSequence = fnGetMainSequence( thiscomponent.DrawPages(0) )
 
	dim message as string
	dim newline as string
 
	newline = chr(10)
 
	if HasUnoInterfaces( oMainSequence, "com.sun.star.container.XEnumerationAccess") then
		oClickNodes = oMainSequence.createEnumeration()
		while( oClickNodes.hasMoreElements() )
			oClickNode = oClickNodes.nextElement()
			fnGetNodeType( oClickNode )
			If IsUnoStruct( oClickNode.begin ) Then
				message = message & "Wait on click" & newline
			Else If IsNumeric( oClickNode.begin ) Then
				message = message & "Wait " & Format( oClickNode.begin, "0.0##" ) & " seconds" & newline
			End If
			End If
 
			oGroupNodes = oClickNode.createEnumeration()
			While( oGroupNodes.hasMoreElements() )
				oGroupNode = oGroupNodes.nextElement()
				 If IsNumeric( oGroupNode.begin ) Then
				 	If oGroupNode.begin > 0 Then
						message = message & "Wait " & Format( oGroupNode.begin, "0.###" )  & " seconds" & newline
					End If			
				End If
 
				oEffectNodes = oGroupNode.createEnumeration()
				While( oEffectNodes.hasMoreElements() )
					oEffectNode = oEffectNodes.nextElement()
					If IsNumeric( oEffectNode.begin ) Then
				 		If oEffectNode.begin > 0 Then
							message = message & "After " & Format( oEffectNode.begin, "0.###" )  & " seconds, "
						End If							
					End If		
 
					message = message & "Play " & getEffectClass( oEffectNode ) & " effect " & getEffectId( oEffectNode ) & newline
				Wend
			Wend
		Wend
	end if
 
	MsgBox message
 
End Sub
 
' This function returns the main sequence from the given draw page
Function fnGetMainSequence( oPage as Object ) as Object
	On Error Resume Next
	oNodes = oPage.AnimationNode.createEnumeration()
 
	While( oNodes.hasMoreElements() )
		oNode = oNodes.nextElement()
		If fnGetNodeType( oNode ) = com.sun.star.presentation.EffectNodeType.MAIN_SEQUENCE  Then
			fnGetMainSequence = oNode
			Exit Function
		End If
	Wend
End Function
 
Function fnGetNodeType( oNode as Object ) as Integer
	On Error Resume Next
	For each oData in oNode.UserData
		If oData.Name = "node-type" Then
			fnGetNodeType = oData.Value
			Exit Function
		End If
	next oData
End Function
 
Function getEffectClass( oEffectNode as Object ) as String
	On Error Resume Next
	For each oData in oEffectNode.UserData
		If oData.Name = "preset-class" Then
			getEffectId = oData.Value
			Exit Function
		End If
	next oData
End Function
 
Function getEffectId( oEffectNode as Object ) as String
	On Error Resume Next
	For each oData in oEffectNode.UserData
		If oData.Name = "preset-id" Then
			getEffectId = oData.Value
			Exit Function
		End If
	next oData
End Function
Personal tools