SCRIPTS AND RECIPES

Why would someone want to go to the bother of writing a script to create animation for InDesign when you can do just about everything from the user interface? One reason: “just about” is just that. You can’t do everything from the user interface. Reason two: Writing a script is not hard, and (maybe just for me), a lot more intuitive.

For example. I was having a conversation with a computer savvy person the other day who expressed the feeling that coding is “just too difficult”. My reply was that it is no more difficult than telling someone how to bake a cake. With code, you are telling the computer how to “bake” that “cake.” And, what’s more, there are so many recipes “out there” that you can take a recipe from another and, with a tweak here and there, make it your own.

This is what this blog series is all about, taking instructions from another “recipe” and adding your own ingredients and procedures to make it your own. The “recipe” we are following is a script provided from Adobe: “AnimationEncyclopedia”. (You will find it in the Scripts panel for InDesign.)

The Cake

The “cake” we will bake in this blog post will be an animation that takes one second to move an object from the left side of the screen to the center, pauses for a second, and then moves it off the opposite side.

Creating the object

To begin, we will need to create an object. To keep it simple, we will start with a rectangle. In the AnimationEncyclopedia script there is a handler (function) for creating a rectangle:

Applescript

on myMakeRectangle(myPage, myBounds, myString, myFillColor, myStrokeColor, myStrokeWeight)
   tell application "Adobe InDesign CC 2017"
      tell myPage
	set myRectangle to make rectangle with properties {geometric bounds:myBounds, name:myString, fill color:myFillColor, stroke color:myStrokeColor, stroke weight:myStrokeWeight}
	return myRectangle
      end tell
   end tell
end myMakeRectangle


JavaScript

function myMakeRectangle(myPage, myBounds, myString, myFillColor,  myStrokeColor, myStrokeWeight){
	var myRectangle = myPage.rectangles.add({geometricBounds:myBounds, fillColor:myFillColor, strokeWeight:myStrokeWeight, strokeColor:myStrokeColor, name:myString});
	return myRectangle;
}

This is called by a statement similar to:
Applescript:

set myRectangle1P6 to my myMakeRectangle(page 6, {1.625, 1, 2, 2}, "Scripted Animation Rectangle", "Purple", "None", 0): 

JavaScript:

myMakeRectangle(myDocument.pages.item(5), [0,0,8.333,11.111], "Background Rectangle", myLightGray, myNoneSwatch, 0); 

Ingredients (Arguments)

Arguments for a handler/function are enclosed in parentheses following its name. As you can see, the call is sending the following required “ingredients”:

  • a reference to the document page
  • the geometric x-y coordinates for the object (bounds)
  • a string (the rectangle name)
  • a color for the fill
  • a color for the stroke
  • the stroke weight

After creating the rectangle, the handler/function will return a reference to the object to the main part of the script:

   return myRectangle

GETTING THE INGREDIENTS

The Page

With a script, we can get a page reference from the application We will also need to make sure that we have an active document set up correctly for the web.

   tell application "Adobe InDesign CC 2017"
      set measurement unit of script preferences to pixels
      set ruler origin of view preferences of document 1 to page origin
      set blending space of transparency preferences of document 1 to RGB
      set spreadRef to active spread of active window
      set pageRef to page 1 of spreadRef
   end tell

Geometric Bounds

The geometric bounds is a list/array of four numeric values, top (y0), left (x0), bottom (y1), right (y1). Fo our purpose, the x1 and y1 values will be based on the width and height of the page (pageRef). But first we will need to define the width and height for our rectangle. We can do that at the top of the script.

   set rectWid to 60
   set rectHgt to 30

Since these measurements are in pixels, we need to make sure that measurements for the script will be set to pixels. We can put this right after the tell statement to InDesign:

   set measurement unit of script preferences to pixels

To create the rectangle off the right side of the page, we will need to get the width and height of the page and then calculate the center for the horizontal (x) dimension and the vertical (y) dimension.

   copy bounds of pageRef to {pagey0, pagex0, pagey1, pagex1}
   set cx to round ((pagex1 - pagex0) / 2)
   set cy to round ((pagey1 - pagey0) / 2)

With this we can create the geometric bounds for our rectangle off the right side of the page and centered vertically:

   set gBounds to {cy, pagex1, cy + rectHgt, pagex1 + rectWid}

Color

For fill color, you can use any color that exists in your document. We will use “Paper.” For stroke color, again you can use any color that exists in your document. We will use “Black”

	set whiteColor to swatch "Paper" of document 1
	set blackColor to swatch "Black" of document 1

String Value (name)

For this we will simply use a string value for the argument

CALL THE HANDLER/FUNCTION

With this we have the ingredients (arguments) for our recipe. With “Rect1” for the name of the rectangle to be created we can add a call to the myMakeRectangle handler/function and pass it the arguments it requires.

   set rectRef to my myMakeRectangle (pageRef, gBounds, "Rect1", whiteColor, blackColor, 2)

TEST

The top of the script at this point should read as follows (don’t forget to add the myRectangle handler/function at the bottom):

   set rectWid to 60
   set rectHgt to 30
   tell application "Adobe InDesign CC 2017"
       set measurement unit of script preferences to pixels
       set ruler origin of view preferences of document 1 to page origin
       set blending space of transparency preferences of document 1 to RGB
       set spreadRef to active spread of active window
       set pageRef to page 1 of spreadRef	
        copy bounds of pageRef to {pagey0, pagex0, pagey1, pagex1}
	set cx to round ((pagex1 - pagex0) / 2) --center horizontal
	set cy to round ((pagey1 - pagey0) / 2) --center vertical
	set gBounds to {cy, pagex1, cy + rectHgt, pagex1 + rectWid}
	set whiteColor to swatch "Paper" of document 1
	set blackColor to swatch "Black" of document 1
	set rectRef to my myMakeRectangle(pageRef, gBounds, "Rect1", whiteColor, blackColor, 2)
   end tell

You should be able to run the script and see your rectangle off the right side and in the vertical center of the page.

ADDING ANIMATION

One advantage of using a script for animations in InDesign is the fact that a script can address the timeline. We will take advantage of this by setting the timeline to 2 seconds:

   set duration to 2

With each second of the timeline having 24 timeframes, we know that the beginning timeframe will be 0, with 23 being that for one second (amount of seconds times 24 minus one).

The motion path for an object is defined using a list of lists (array of arrays). Each item in the list (array) describes two values:

  • the timeframe
  • the position of the object

The position for the object is an anchor point which requires three lists (arrays) of x-y values.

The motion path is set as part of the animation settings for the object usually following a statement that defines the duration (total time for the animation).

    set duration to 2   
    set motion path to {{0, {{0, 0}, {0, 0}, {0, 0}}}, {23, {{-cx, 0}, {-cx, 0}, {-cx, 0}}}, {47, {{-cx, 0}, {-cx, 0}, {-cx, 0}}}}

This can be followed with settings for other property values. These properties are optional but the animation settings will default to something you may not expect if not included.

    set plays to 1
    set ease type to no ease
    set transform offsets to {0.5, 0.5}
    set design option to to current appearance
    set initially hidden to false
    set hidden after to false 

The properties above are pretty self-explanatory with the exception of design option.

Design Option

The design option can be set to either from current appearance or to current appearance. What requires explanation is that when using to current appearance, the values for the motion path take a little getting used to.

Think of it this way: The amount of motion is defined from where the current object is. Therefore if a positive value is used, the object will move in a negative direction. To move an object horizontally, a negative value for the x coordinate is used. To move the object from the left side of the page to where it is being created (at the right side of the page), we use the following for the motion path:

   set motion path to {{0, {{0, 0}, {0, 0}, {0, 0}}}, {23, {{-pagex1, 0}, {-pagex1, 0}, {-pagex1, 0}}}}

TEST IT

Add the properties from above to your script just below the statement that creates the rectangle. Put this inside a tell statement directed to the spread.

tell spreadRef
   tell animation settings of rectRef
	set duration to 2
	set motion path to {{0, {{0, 0}, {0, 0}, {0, 0}}}, {23, {{-pagex1, 0}, {-pagex1, 0}, {-pagex1, 0}}}}
	set plays to 1
	set ease type to ease in out
	set transform offsets to {1, 0.5}
	set design option to to current appearance
	set initially hidden to false
	set hidden after to false
	end tell
   end tell

Clear your screen of any rectangles that are there from previous tests and run the script. Open the EPUB Interactivity Preview panel from InDesign’s Window > Interactive menu. 

Clear the Preview screen if needed.

 Play the Preview (Option Click to run the Preview again). 

Click and drag on a corner of the preview window to enlarge the screen so you can see the animation better.

ADDING TO THE ANIMATION

To change the animation for the object we just need to change the values for duration and the settings for each time frame where a change in direction or other value occurs. Below we set the animation to move the rectangle to the center of the page and then off to the right. (Notice that we are also changing the value for duration.)

   set duration to 5
   set motion path to {{0, {{0, 0}, {0, 0}, {0, 0}}}, {23, {{-cx, 0}, {-cx, 0}, {-cx, 0}}}, {47, {{-cx, 0}, {-cx, 0}, {-cx, 0}}}, {95, {{-pagex1, 0}, {-pagex1, 0}, {-pagex1, 0}}}}

Change the Ease Value

Values that can be set for the ease value are: no ease, ease in, ease out, ease in out, and custom ease. Try setting the ease value to ease in out. Watch the rectangle change its velocity (ever so slightly) as it enters and leaves the screen. It’s more noticeable on the ease out when it exits.

<h3

To have the rectangle repeat its animation, change the value for the animation setting Plays to some other value.

   set plays to 3

ADD MORE RECTANGLES

In case you want rectangles of different colors, you can add any number of rectangles. In this case we will create the rectangles to use the same animation settings.

    • First define variables for the other swatches in your document that you will be using:
	set redColor to swatch "RGB Red" of document 1
	set blueColor to swatch "RGB Blue" of document 1
    • Next copy the statement for setting rectRef and paste below. Change the values for the object references, the names, and the colors.
set rectRef1 to my myMakeRectangle(pageRef, gBounds, "Rect1", whiteColor, blackColor, 2)
set rectRef2 to my myMakeRectangle(pageRef, gBounds, "Rect2", whiteColor, blackColor, 2)
set rectRef3 to my myMakeRectangle(pageRef, gBounds, "Rect3", whiteColor, blackColor, 2)
    • set the animation properties inside a repeat with statement directed to the spread:
tell spreadRef
   repeat with eachItem in {rectRef1, rectRef2, rectRef3}
      tell animation settings of eachItem
	set duration to 5
	set motion path to {{0, {{0, 0}, {0, 0}, {0, 0}}}, {23, {{-cx, 0}, {-cx, 0}, {-cx, 0}}}, {47, {{-cx, 0}, {-cx, 0}, {-cx, 0}}}, {95, {{-pagex1, 0}, {-pagex1, 0}, {-pagex1, 0}}}}
	set plays to 1
	set ease type to ease in out
	set transform offsets to {1, 0.5}
	set design option to to current appearance
	set initially hidden to false
	set hidden after to false
      end tell
   end repeat
end tell

Test It

Compile the script, clear the document of rectangles from previous tests, and run. Your rectangles should enter, pause, and then leave the page one after the other.

ON PAGE CLICK

To have your animation run only when the page is clicked, you will need to work with the spread’s timing list.

 

    • First remove the default timing list and create a new one.
tell timing settings of spreadRef
   tell timing settings of spreadRef
      delete timing list 1
      set timingListRef to make timing list with properties {trigger event: on page click}
   end tell
end tell 
    • Next: create a timing group for each of the items inside a tell statement to the new timing list created (timingListRef):
tell timingListRef
   set timingGroupRef1 to make timing group with properties {dynamic target:rectRef1, delay seconds:0}
   set timingGroupRef2 to make timing group with properties {dynamic target:rectRef2, delay seconds:0}
   set timingGroupRef3 to make timing group with properties {dynamic target:rectRef3, delay seconds:0}
end tell

With this, each of your items will display one after the other when the page is clicked. Notice that you can set a delay value to initiate a delay before each item animates.

Only one item timing group? Yes, and you will see why in the next post for this blog post series. Until then, experiment with this script. Change the motion path, change colors, add delays. If you are really brave, try placing graphics to animate instead of creating rectangles. Have fun.<>/p>

</h3