Your prescription for increased productivity and profitability
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” 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.
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);
Arguments for a handler/function are enclosed in parentheses following its name. As you can see, the call is sending the following required “ingredients”:
After creating the rectangle, the handler/function will return a reference to the object to the main part of the script:
return myRectangle
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
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}
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
For this we will simply use a string value for the argument
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)
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.
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 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.
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}}}}
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.
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}}}}
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
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.
set redColor to swatch "RGB Red" of document 1 set blueColor to swatch "RGB Blue" of document 1
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)
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
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.
To have your animation run only when the page is clicked, you will need to work with the spread’s timing list.
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
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