You Have Reached the Top

If you are an adamant hiker like me, you have discovered once you have reached the top of a ridge, the mountain before you just continues to rise upward. So, here you are at the top of the automate animation ridge, but there is so much more that you can do. Before you start the next leg of the climb, settle back and take a breather to review your progress so far. Our project for this week will help with that review. Here we will use three handlers from previous blog installments:

  • toCurrentLocation – moves an object horizontally using the motion path points property
  • setRotateProps – sets rotation for object passed to the handler
  • createTimingGroups – deletes the current timing list and creates a new one for the spread

To wrap up our first section on automating animation for fixed layout Epubs we will create a script that can be used to animate any object that has wheels such as a bicycle or wagon. This can be part of a page exported as an Adobe InDesign fixed layout ePub for viewing electronically.

My Bicycle

For the bicycle artwork, take advantage of assets provided with your Creative Cloud membership: a nice rendering of a bicycle. To separate the wheels from the bicycle, bring the artwork into Photoshop and do a little judicious cutting and pasting.

Next, bring the elements into an InDesign CC 2014 document created for web intent measuring 1024 by 768.

 Bicycle parts imported to InDesign

Assemble the bicycle parts near the right side of the page.

First, you will want to name the bicycle parts. To do so, select each element, one at a time, and run the following script. This is a script I use often, so I have it saved in InDesign’s Scripts folder with a keyboard shortcut assigned.

Name Selected

   --Gives user a dialog for naming a selected object
   set promptStr to "Enter name for selected object"
   tell application "Adobe InDesign CC 2014"
      try
	set selList to selection
	set selItem to item 1 of selection
	set name of selItem to my getString(promptStr)
      on error errStr
	activate
	display alert "Error " & errStr
      end try
   end tell
   (*Gets string response from user; otherwise throws error*)
   on getString(promptStr)
        set userResponse to display dialog promptStr default answer "" default button 2
	if text returned of userResponse = "" then
	    error "Valid string not entered"
	end if
	return text returned of userResponse
   end getString

You can name the elements anything you want, but for our purpose name the bicycle frame “Frame” and the wheels “BackWheel” and “FrontWheel”.

   Dialog created when script is run

Because the elements will travel as one unit, group the elements and name them “Bicycle.” Save your document.

For the script, we will dip into our collection of AppleScript animation handlers. Copy and paste the following handlers to a new script in your AppleScript editor. (For those of you who use ExtendScript, you can follow along; the process is the same.)

toCurrentLocation

   (*Animates object along horizontal path using motion path points*)
   on toCurrentLocation(objRef, dTime, dTravel, numTimes, tOffsets)
	--default List of lists for straight line path
	set mPathPoints to {{{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}}, true}
	--update mPathPoints list of lists using dTravel variable
	repeat with i from 1 to 3
	   set item 1 of item i of item 2 of item 1 of mPathPoints to dTravel
	end repeat
	tell application "Adobe InDesign CC 2014"
	   tell animation settings of objRef
		set duration to dTime
		set design option to to current location
		set motion path points to mPathPoints
		set transform offsets to tOffsets
		set plays to numTimes
	   end tell
	end tell
   end toCurrentLocation

setRotateProps

   (*Rotates object given rotation array, duration, and repeat*)
   on setRotateProps(objRef, rArray, dTime, numTimes, tOffsets)
      tell application "Adobe InDesign CC 2014"
          tell animation settings of objRef
             set transform offsets to tOffsets
             set duration to dTime
             set rotation array to rArray
             set plays to numTimes
         end tell
      end tell
   end setRotateProps

createTimingGroups

This handler has been updated to allow a group having any number of child elements to be controlled by the timing settings for its spread. The trigger event to start the animation is on page click.

   on createTimingGroups(spreadRef, parentGroup, childElements)
      tell application "Adobe InDesign CC 2014"
	set spreadRef to spread 1 of document 1
	tell timing settings of spreadRef
	   delete timing lists
	   set tList to make timing list with properties {trigger event:on page click}
	end tell
	tell tList
	   set g1 to make timing group with properties {dynamic target:parentGroup, delay seconds:0.0}
	      tell g1
		 repeat with eachItem in childElements
		    make timing target with properties {dynamic target:eachItem, delay seconds:0.0}
		 end repeat
	      end tell
	   end tell
	end tell
   end createTimingGroups

Now to Animate

Rotation

You might want to test out your rotation animation with a test object. This can be just a colored square placed anywhere on the page. Add the following to your script with the handlers above added. Select the page item in Indesign and run your script.

   set rArray to {{0,0.0}, {23, 180.0}} --rotate 360 degrees in 1 second
   set rTime to 1 --duration for the rotation
   set tOffsets to {0.5, 0.5} --center point for rotation
   set numTimes to 1 --number of times to repeat animation
   tell application "Adobe InDesign CC 2014"
      set eachItem to item 1 of selection
   my setRotateProps(eachItem, rArray, rTime, numTimes, tOffsets)
   end tell

Preview the animation in InDesign’s EPUB Interactivity Preview panel (option+shift+return). You may want to play around with the animation settings. For instance, to really speed up the rate at which the object rotates, change the value of rArray to {{0.0,0.0},{11, 360.0}} (rotates full circle in one half second).

   set rTime to 0.5 --duration for rotation is one-half second

When you are happy with the rotation, delete the test item from the page. Make sure you save the document afterwards. You will want to be able to revert your document to this point in the event something weird happens with your animation.

Now change the top of the script to read as follows:

   set rArray to {{0, 0.0}, {23, 360.0}} --rotation array
   set rTime to 1.0 --duration for rotation
   set dTime to 3.0 --duration for animation
   set tOffsets to {0.5, 0.5}
   set numTimes to 1
   set dTravel to 930
   tell application "Adobe InDesign CC 2014"
      set spreadRef to spread 1 of document 1
      set groupRef to group "Bicycle" of spreadRef
      set wheel1Ref to page item "BackWheel" of groupRef
      set wheel2Ref to page item "FrontWheel" of groupRef
      set childItems to {wheel1Ref, wheel2Ref}
      repeat with eachItem in childItems
         my setRotateProps(eachItem, rArray, rTime, numTimes, tOffsets)
      end repeat
      my toCurrentLocation(groupRef, dTime, dTravel, numTimes, tOffsets)
      my createTimingGroups(spreadRef, groupRef, childItems)
   end tell

Save your script somewhere special. This can be a good starting point for a variety of scripts that animate a group which has any number of child elements. Notice how each item repeat loops simplify the process of writing the script. Remember that the reference to each item in a repeat with loop is an object.

Bicycle after animation script is run

You will need to create the project to see the animation for yourself. Open InDesign’s EPUB Interactivity Preview panel, press the start button and then touch the display area to start the animation. (Remember, the script sets the animation to start on page click.)

Challenge:

Add a rider for your bicycle.
Add easing so the bicycle slows down as it approaches the end of its travel.
Have fun!