Your prescription for increased productivity and profitability
When it comes to writing scripts to create animations in InDesign, defining the motion path for your object may become your number one headache.
To set up a path for animating a page object to travel in a straight line is not as simple as it sounds:
The problem here is that each point in the path is a list of three points: the anchor, the left direction control, and right direction control. The array (list) to describe this gets a little scary when there are a number of points to define.
When a point does not define a curve, all three coordinate pairs for the point are the same. Try the following script with a single page document in InDesign open. Run the script and view the result in EPUB Interactivity Preview panel (Window > Interactive > EPUB Interactivity Preview).
set gBounds to {90, 0, 110, 100} set pathPoints to {{{{0, 200}, {0, 200}, {0, 200}}, {{500, 200}, {500, 200}, {500, 200}}}, true} set numberSeconds to 2 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 spreadRef to active spread of active window set objStyle to object style 1 of document 1 set rectRef to my makeDefaultRectangle(spreadRef, gBounds, objStyle) tell animation settings of rectRef set design option to from current appearance set duration to numberSeconds set transform offsets to {1, 0} set motion path points to pathPoints set plays to 1 end tell end tell on makeDefaultRectangle(spreadRef, gBounds, objStyle) tell application "Adobe InDesign CC 2017" tell spreadRef set myRectangle to make rectangle with properties {geometric bounds:gBounds, object style:objStyle} end tell end tell end makeDefaultRectangle
var gBounds = [90,0, 110, 100]; var pathPoints = [[[[0, 200], [0, 200], [0, 200]], [[500, 200], [500, 200], [500, 200]]], true]; var numberSeconds = 2; app.scriptPreferences.measurementUnit = MeasurementUnits.PIXELS; var docRef = app.documents.item(0); docRef.viewPreferences.rulerOrigin = RulerOrigin.PAGE_ORIGIN; var spreadRef = docRef.spreads.item(0); var objStyle = docRef.objectStyles.item(0); var rectRef = makeDefaultRectangle(spreadRef, gBounds, objStyle); rectRef.animationSettings.duration = numberSeconds; rectRef.animationSettings.designOption = DesignOptions.FROM_CURRENT_APPEARANCE; rectRef.animationSettings.motionPathPoints = pathPoints; rectRef.animationSettings.transformOffsets = [1, 0]; rectRef.animationSettings.plays = 1; function makeDefaultRectangle(spreadRef, gBounds, objStyle) { var myRectangle = spreadRef.rectangles.add({geometricBounds:gBounds, ObjectStyle:objStyle}); return myRectangle; }
Change just one coordinate for a direction control, and suddenly your path becomes a curve. Change the list for the pathPoints variable above to read as follows and test.
set pathPoints to {{{{0, 200}, {0, 200}, {0, 200}}, {{500, 200}, {500, 50}, {500, 200}}}, true}
var pathPoints = [[[[0, 200], [0, 200], [0, 200]], [[500, 200], [500, 50], [500, 200]]], true];
Try adding a point in the center of the path and experiment with setting the left and right curve controls:
set pathPoints to {{{{0, 200}, {0, 200}, {0, 200}}, {{250,200}, {250, 50}, {250, 350}}, {{500, 200}, {500, 200}, {500, 200}}}, true}
var pathPoints = [[[[0, 200], [0, 200], [0, 200]], [[250,200], [250, 50], [250, 350]], [[500, 200], [500, 200], [500, 200]]], true]
Adding timing values (keyframes) to the motion path definition increases the difficulty in writing the Motion Path array. But it is not that hard if you break the process down:
…adding keyframes to motion path
set pathPoints to {{0, [{0, 200}, {0, 200}, {0, 200}}], {23, {{250,200}, {250, 50}, {250, 350}}}, {47, {{500, 200}, {500, 200}, {500, 200}}}}
Notice that the pathPoints array above no longer has the true (path open boolean) at the end. When working with keyframes you use the motion path property instead of the motion path points property for animation settings.
The AppleScript dictionary makes this very clear. (The animation settings property is found in the preferences suite.)
motion path (list of any): The list of motion path points and key frames for this animation…
The motion path points property does not include key frames but does require the path open boolean:
motion path points (any): The list of motion path points for this animation…path open:boolean
Also make sure to change the duration (numberSeconds variable) to accommodate the number of keyframes. For instance: for an animation having three keyframes of 1 second each, you will need to increase the value for numberSeconds (duration) to 3.
set numberSeconds to 3 ...
tell animation settings of rectRef set design option to from current appearance set duration to numberSeconds set transform offsets to {0.5, 0.5} set motion path to pathPoints set plays to 1 end tell
Now that you have the basics for creating the Motion Path array, the next problem is how to determine the values for each point. Plotting paths with non-curve points is fairly simple, especially if you can calculate the points mathematically. But mathematics can turn into a brain teaser especially if curves are involved. Let InDesign do the work for you.
Start with a document the same size as your completed animation.
Create your animation object at its starting position on the page. Hint: use your script with the animation settings commented out:
set gBounds to {90, 0, 110, 100} 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 spreadRef to active spread of active window set objStyle to object style 1 of document 1 set rectRef to my makeDefaultRectangle(spreadRef, gBounds, objStyle) --comment out animation settings (*tell animation settings of rectRef set design option to from current appearance set duration to numberSeconds set transform offsets to {1, 0} set motion path points to pathPoints set plays to 1 end tell*) end tell --add makeDefaultRectangle handler here
With the path and the page item selected, run the following script:
tell application "Adobe InDesign CC 2017" set selList to selection set selItem to item 1 of selList tell animation settings of selItem set thePath to motion path points end tell end tell thePath
var selList = app.selection; var selItem = selList[0]; var thePath = selItem.animationSettings.motionPathPoints; thePath
Copy the Result from running the script. For the pathPoints variable at the top of the script, paste in the result. Change the value of the numberSeconds variable to correspond with the number of points in the path. Uncomment the animation settings portion of the script. The script for an arbitrary path of five non-curve points without keyframes will read similar to the following:
set gBounds to {90, 0, 110, 100} set pathPoints to {{{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, {{161.0, -65.0}, {161.0, -65.0}, {161.0, -65.0}},¬ {{286.0, 101.0}, {286.0, 101.0}, {286.0, 101.0}}, {{425.0, 21.0}, {425.0, 21.0}, {425.0, 21.0}},¬ {{678.0, 194.0}, {678.0, 194.0}, {678.0, 194.0}}}, true} set numberSeconds to 5
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 spreadRef to active spread of active window set objStyle to object style "[Basic Graphics Frame]" of document 1 set rectRef to my makeDefaultRectangle(spreadRef, gBounds, objStyle) tell animation settings of rectRef set design option to from current appearance set duration to numberSeconds set transform offsets to {1, 0} set motion path points to pathPoints set plays to 1 end tell end tell --add makeDefaultRectangle handler here
Delete the path and animated page item from the page and run your script with the motion path points from the getPathPoints script added.
Convert to Motion Path does not take timing keyframes into consideration. To add keyframes the frame value is added to each point in the motion path as needed. (See discussion above.) The pathPoints variable above will now read as follows:
set mpath to {{0, {{0, 0}, {0, 0}, {0, 0}}}, {23, {{200, 0}, {200, 0}, {200, 0}}}, ¬ {47, {{200, 200}, {200, 200}, {200, 200}}}, {119, {{0, 200}, {0, 200}, {0, 200}}}, {143, {{0, 0}, {0, 0}, {0, 0}}}}
Notice that the open path boolean (true) is removed as we will be using the motion path property instead of motion path points.
tell animation settings of rectRef set design option to from current appearance set duration to numberSeconds set transform offsets to {.5, .5} set motion path to mPath set plays to 1 end tell
Remove the original animation from the page and run the script that now has keyframes added. Preview the animation in the EPUB Interactivity Preview panel.
Now that you have added keyframes, wouldn’t it be interesting to rotate the page item as its angle of direction changes. Adding rotation (rotation array) is easy, but figuring out what the angle settings need to be is another matter. Again, let InDesign do the work for you. Click on the animated page item to reveal the motion path. Use the ruler tool to draw a line over the path segment.
Now open the info panel (Window > Info) and read the angle setting there. The only problem is that you need to reverse the positive/negative signs for the angle reported. So if the angle reads 22, use -22. With this adjustment our rotation array values were set as follows (yours will be different):
set rotArray to {{0,0}, {23, -22}, {47, 53}, {71, -29.4}, {95, 34.3}}
Add the rotation array to the animation settings for the animated page item:
tell animation settings of rectRef set design option to from current appearance set duration to numberSeconds set transform offsets to {0.5, 0.5} set motion path to mPath set rotation array to rotArray set plays to 1 end tell
Remove the previous animation from the page, and run the script with rotation values added. View the animation in the EPUB Interactivity Preview panel.
The problem is that the rotation angle for the animated page item changes gradually between points. You may wish to change the angle sooner and have the angle maintained until the next point is reached. You are not limited to setting rotation values at the same keyframes as the motion path. For the purpose of demonstration, we added a keyframe midway between the motion path points to force the rotation to occur earlier and then keep the same rotation at the next motion path point:
set rotArray to {{0, 0}, {11, -22}, {23, -22}, {36, 53}, {47, 53}, {60, -29.4},¬ {71, -29.4}, {84, 34.3}, {95, 34.3}}
Do some experimenting with your animation: change the path, change the rotation array, change the keyframe values. Have fun with it.
Now that you are familiar with motion path points and motion path, try creating a path that includes curves. Use the same procedure as above taking advantage of InDesign’s ability to convert two selected objects to a motion path and have it calculate the path for you.