Animation Paths: Motion Path Points

To this point, all of our animation scripts have involved either a vertical or horizontal direction of travel. Our Fly In script (March 8) started by setting the list value for the variable <em>dTravel</em>  as {800, 0.0}. This set the path of travel for the page item selected 800 pixels horizontally and 0 pixels vertically. If you experimented with the values for this variable you discovered that a negative value for the first value of the list would move the page item from right to left. For a vertical direction of travel, the first value for the dTravel list would be zero (0.0) with the second value indicating the vertical distance of travel. A positive value for the second list item moves the selected page item from top toward the bottom; a negative value moves the item from bottom toward the top.

To review, create a document for Digital Publishing intent (1024 x 768). Place a page item somewhere near center on the page. Open your Fly In script or copy and paste the following into AppleScript Editor. Change the value for the dTravel variable to {-800, 0.0}.

Fly In Script

   tell application "Adobe InDesign CC 2014"
      set selList to selection
      set objRef to item 1 of selList
      set name of objRef to "Object1"
      set dTravel to {-800, 0.0} --relative path for travel
      set dTime to 1 --duration
      set numTimes to 1 --number of times to repeat
      set tOffsets to {0.5, 0.5} --transform point set for center of item's bounds
      --call to toCurrentLocation handler
      my toCurrentLocation (objRef, dTime, dTravel, numTimes, tOffsets)
   end tell
   (*toCurrentLocation handler*)
   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}}}, true}
      --update mPathPoints list of lists using dTravel variable
      repeat with i from 1 to 3
         set 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 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 

With the page item selected, run the script and preview the animation in InDesign’s EPUB Interaction Preview panel (option+shift+return).

If you provide a value other than 0.0 for both items of the dTravel list variable, the direction of travel will be a diagonal. Change the value for dTravel in your script to {600, 100} and test. The direction of travel will be a diagonal from top left.

shows diagonal path created by script

To understand how this works, a brief review of high school geometry may be in order. If you recall, Cartesian coordinates provide a method of indicating the position of points on a two-dimensional plane (also three-dimensional space, but we can ignore that). The Cartesian plane consists of two perpendicular axes that cross at a central point called the origin. Positions in the plane (coordinates) are determined according to the east/west (x) and north/south (y) displacements from the origin. With the to current location design option for an object’s animation settings, the origin is the transform offset for the page item.

Transform Offsets

The transform offsets property for an object’s animation settings is a list of two values which determines the “pin” point for the object’s animation. Starting with {0.0, 0.0} for the top left corner of the object’s bounding box, the list values are a percentage (0.0 to 100.0) of the bounding box width and height. As with all positional coordinate lists, the first value represents the horizontal value, and the second its vertical value.

Moving an Object

The concept for moving an object can be summarized as follows:

    Horizontal travel (x)
  • Positive value moves object from left to right
  • Negative value moves object from right to left
    Vertical travel (y)
  • Positive value moves object from top to bottom
  • Negative value moves object from bottom to top

Update Fly In Script

When you want to move a page item in from outside the page, for convenience you can use the Fly In Script and just make educated guesses as to the values required for the dTravel list values. However, with an understanding of the concepts above, you can modify the calculateRelativeMove handler to allow it to calculate both the x and y list values for both straight and diagonal paths of travel. For this a variable rMove will be used to indicate the percentage of the move for each direction. Whether each of the list values for this variable is positive or negative will determine the direction of the move. You can see how this works with the modified script below. The top part of this script is very similar to the original.

Modified Fly In Script

   (*Provides handler to calculate values for diagonal directions of travel*)
    tell application "Adobe InDesign CC 2014"
       set selList to selection
       set objRef to item 1 of selList
       set name of objRef to "Object1"
       --percentage of travel distance from page side for horizontal and vertical
       set rMove to {1.0, 1.0}--move from top left
       set tOffsets to {1, 0.5} --left side centered vertically
       (*the script now passes the rMove variable to calculateRelativeMove handler
       which passes back the list of values for the dTravel variable*)
       set dTravel to my calculateRelativeMove(objRef, rMove, tOffsets)
       set dTime to 1 --duration
       set numTimes to 1 --number of times to repeat
       my toCurrentLocation(objRef, dTime, dTravel, numTimes, tOffsets)
    end tell
    (*Calculates relative distance for move and returns list*)
    on calculateRelativeMove(objRef, rMove, tOffsets)
       tell application "Adobe InDesign CC 2014"
          set selList to selection
          set objRef to item 1 of selList
          set pageRef to parent page of objRef
          copy bounds of pageRef to {py0, px0, py1, px1}
          copy geometric bounds of objRef to {y0, x0, y1, x1}
          set pageWid to px1 - px0
          set pageHgt to py1 - py0
          set itemWid to x1 - x0
          set itemHgt to y1 - y0
          if item 1 of rMove > 0 then
             set xMove to ((item 1 of rMove) * x0)
          else
             set xMove to ((item 1 of rMove) * (pageWid - x1))
          end if
          if item 2 of rMove > 0 then
            set yMove to ((item 2 of rMove) * y0)
          else
             set yMove to ((item 2 of rMove) * (pageHgt - y1))
          end if
       end tell
       return {xMove, yMove}
    end calculateRelativeMove
    --Add toCurrentLocation handler from the original Fly In Script (above)

You will want to experiment with the modified script to see how the values in the rMove list affects the object’s direction of travel.

Understanding Paths

Motion Path Points

The toCurrentLocation handler in the script above starts with the motion path points property for animation settings being 0.0 for horizontal and 0.0 for vertical for both the start and stop points.

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}}}, true}

The fact that this is a list of lists of lists takes some getting used to. If you look carefully you will see that the value for the second item of the list is a boolean (true). A value of true indicates that the path is an open path. The actual value for the path points (item 1 of the list) is nothing more than two sets of lists each representing a point along the path (start and finish). Each of these consists of three lists to describe a path point. Each of these contain two values for the relative distance to move: horizontal, then vertical. So why three lists to describe one path point? Each point on a path can be a curve (Bezier curve) so it needs to describe the anchor point, the left direction, and right direction for the curved point. When all three values for the path point are the same, the point has no curve. Notice how the toCurrentLocation handler updates each of the three lists for the ending path point. No stress!

Jump and Jive

But what if you don’t want your page item to fly in on a straight path? The following discussion may take a little brain power, but take our word for it, once you work with it, it will start to make sense.

Constructing a path of non-curve path points is relatively simple.
Once you have the amount of relative move (calculated from the calculateRelativeMove handler), the toCurrentLocation handler can calculate the points along the path. For this, your script will need to supply the handler a list of lists.

    • Each item in the list will contain two values:
    • The first value defines a point along the path as a percentage of the total horizontal move.
    • The second value defines the vertical deviation from the straight path at each given point.
   set pathDevList to {{0.3, 100}, {0.5, -100}, {0.7, 200}, {1, 0}}
  • The script does the rest.

Modify the toCurrentLocation handler in your Modified Fly In script above

   on toCurrentLocation(objRef, dTime, dTravel, pathDevList, numTimes, tOffsets)
      if pathDevList = {} then
         set mPathPoints to {{{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, {dTravel, dTravel, dTravel}}, true}
      else --build the mPathPoints list of lists
         set mPathPoints to {{}, true}
         set myPathPoints to {{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}}
         copy dTravel to {hTravel, vTravel}
         repeat with i from 1 to length of pathDevList
             set pathDevs to item i of pathDevList
             set pctXTravel to ((item 1 of pathDevs) * hTravel)
             set pctYTravel to ((item 1 of pathDevs) * vTravel) + (item 2 of pathDevs)
             --add three lists for anchor, left, right for each point
             set end of myPathPoints to {{pctXTravel, pctYTravel}, {pctXTravel, pctYTravel}, {pctXTravel, pctYTravel}}
             set item 1 of mPathPoints to myPathPoints
         end repeat
      end if
      --add animation properties to object
      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 transformOffsets to tOffsets
             set plays to numTimes
         end tell
      end tell
      return mPathPoints
    end toCurrentLocation

Modify the top part of the script so it reads as follows:

   set pathDevList to {{0.3, 100}, {0.5, -100}, {0.7, 200}, {1, 0}}
   tell application "Adobe InDesign CC 2014"
      set selList to selection
      set objRef to item 1 of selList
      set name of objRef to "Object1"
      --travel percentage from object relative to page side for horizontal and vertical
      set rMove to {1.0, 1.0}
      set tOffsets to {0, 0.5} --left side of object's bounds centered vertically
      (*the script now passes the rMove variable to calculateRelativeMove
      which passes back the list of values for the dTravel variable*)
      set dTravel to my calculateRelativeMove(objRef, rMove, tOffsets)
      set dTime to 1 --duration in seconds
      set numTimes to 1 --number of times to repeat
      --calls the modified toCurrentLocation handler
      set testPoints to my toCurrentLocation(objRef, dTime, dTravel, pathDevList, numTimes, tOffsets)
   end tell

Notice that the value for mPathPoints is passed back just for testing. In fact, for testing, comment out the tell block to InDesign in the handler. Test to make sure the values returned back from running the script are as anticipated. (When you start working with lists of lists of lists, it can be easy to forget a set of curly braces. Missing just one little curly brace can make InDesign very unhappy when you try to set the motion path points property.)

green line indicates path created

The screnshot above may help clarify how InDesign makes use of the values you give it for the pathDevList variable in this version of the FlyIn Script.

The star for the example is 100×100 pixels

  • Its physical location on the page is 536×440
  • Because the vertical transform offset for the star is set to 0.5, its path starts 50 pixels down from the top of the page.
  • The box bordered with orange measures 100 pixels square.
  • The brown line measures the distance from page left, which is approximately 243 pixels.

Compare these values for the pathDevList values and the resulting motion path points list below:

Motion path points passed back from toCurrentLocation handler:
{{{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, {{145.8, 217.0}, {145.8, 217.0}, {145.8, 217.0}}, {{243.0, 95.0}, {243.0, 95.0}, {243.0, 95.0}}, {{340.2, 473.0}, {340.2, 473.0}, {340.2, 473.0}}, {{486, 390}, {486, 390}, {486, 390}}}, true}

The square intersecting the green path and black straight line path to the object demonstrates how a right triangle is created at each path point. You can see that the pathDevList values in the script describe the sides of the right triangle for which the hypotenuse is the path section created by InDesign.

You will want to experiment with this script further to make sure you understand the concept of path points.

Convert to Motion Path

If you find your head swimming at this point, don’t despair, you can always let InDesign calculate motion paths for you. The following procedure can be used for a path with straight points as well as Bezier curves.

  • Start by creating the page item at its desired ending point.
  • Change the swatches panel to None fill and a colored stroke.
  • Use the pen tool to touch the page at the path’s starting point.
  • Then touch the page at each of the desired path points
  • End by touching the pen at the transform offsets location for the object.
  • (Don’t drag the pen at points unless you want Bezier curves.)
  • With the path drawn and selected, hold the shift key down while selecting your page item.
  • In InDesign’s Object menu, click on Interactive and choose Convert to Motion Path from the flyout menu.

Now that you have assigned the motion path to the page item, you can use the object’s motion path points list in a script.

With the page item selected, run the following script:

    tell application "Adobe InDesign CC 2014"
       set selList to selection
       set selItem to item 1 of selList
       set testIt to motion path points of animation settings of selItem
    end tell
  • Copy the result of the script (from AppleScript Editor’s Result panel).
  • In your script, create a variable for the path
  • Paste the copied result for the value of the variable in your script.

There is only one problem with this solution: You don’t discover how easy it is to calculate motion path points.

You may want to come back later and review how to do this as we will be using a similar solution for setting paths that include timing settings in the future. Timing settings allow the script to dictate exactly when and how an object will reach each point on its path of travel. This is where using scripts for animation start showing its real power.