• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

[DOM] Mapping Motion Path Points to Keyframes

Guide ,
Jul 04, 2019 Jul 04, 2019

Copy link to clipboard

Copied

Hi colleagues,

Given an animated PageItem, we can access its motion path using myItem.animationSettings.motionPathPoints[0]. This returns the array of control points (anchor, left, right) that form the Bezier curve. For example, in the figure below we have four path points (indexed 0 to 3.)

To keep it simple, assume duration is 1 (second) and easeType is NO_EASE. Then 24 underlying “keyframes” are generated (24 fps rate) and shown in green when you select the motion path.

MotionPathKeyframes.png

But those keyframe points (and indices) don't seem to be available as a DOM structure. So, suppose I want to modulate some property (say the rotation) with respect to a specific control point (say at index 2). Technically I have to create a rotationArray property in animationSettings, something like:

myItem.animationSettings.rotationArray = [ [keyFrame, rotationValue] ];

Problem is, I don't know which keyFrame (index) will match control point 2. In fact, no keyframe exactly corresponds to that point, which is between 14 and 15. Of course I could compute the closest keyframe index, adjust the rotation value accordingly, etc, but I'm still very intrigued that there is no kind of mapping from control point to keyframes, while all the information is—almost—before our eyes.

Did I miss something?

Thanks for any help or hint.

@+,

Marc

TOPICS
Scripting

Views

1.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jul 04, 2019 Jul 04, 2019

Hi Marc,

hm. Tricky. Perhaps you could create a custom motion preset file from the animation and edit this?

Never tried this but it looks promising. It's just XML describing the animation. Look into:

contents of animationPreset of app.

In the XML I see property Keyframe defined with values for next and anchor .

Here some raw data of a custom motion preset I did:

<AnimationCore Version="1" duration="24000" TimeScale="24000">

<TimeMap strength="0" type="Quadratic">

</TimeMap>

<metadata>

<names>

<name value="

...

Votes

Translate

Translate
Community Expert ,
Jul 04, 2019 Jul 04, 2019

Copy link to clipboard

Copied

Hi Marc,

hm. Tricky. Perhaps you could create a custom motion preset file from the animation and edit this?

Never tried this but it looks promising. It's just XML describing the animation. Look into:

contents of animationPreset of app.

In the XML I see property Keyframe defined with values for next and anchor .

Here some raw data of a custom motion preset I did:

<AnimationCore Version="1" duration="24000" TimeScale="24000">

<TimeMap strength="0" type="Quadratic">

</TimeMap>

<metadata>

<names>

<name value="" langID="en">

</name>

</names>

<Settings xformPtZOffsetPixels="0" xformPtYOffsetPct="0.5" xformPtXOffsetPct="0.5" orientToPath="0">

</Settings>

</metadata>

<PropertyContainer id="headContainer">

<PropertyContainer id="Basic_Motion">

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Motion_X">

<Keyframe next="2138,42.5197" anchor="0,0" previous="0,0" timevalue="0" roving="0">

</Keyframe>

<Keyframe next="1842,150.236" anchor="0,133.228" previous="-2138,116.22" timevalue="6413" roving="1">

</Keyframe>

<Keyframe next="1208,107.717" anchor="0,103.465" previous="-1842,99.2126" timevalue="11938" roving="1">

</Keyframe>

<Keyframe next="2480,107.717" anchor="0,107.717" previous="-1208,107.717" timevalue="15561" roving="1">

</Keyframe>

<Keyframe next="0,246.614" anchor="0,246.614" previous="-2480,153.071" timevalue="23000" roving="0">

</Keyframe>

</Property>

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Motion_Y">

<Keyframe next="2138,9.92126" anchor="0,0" previous="0,0" timevalue="0" roving="0">

</Keyframe>

<Keyframe next="1842,73.7008" anchor="0,38.2677" previous="-2138,2.83465" timevalue="6413" roving="1">

</Keyframe>

<Keyframe next="1208,233.858" anchor="0,153.071" previous="-1842,72.2835" timevalue="11938" roving="1">

</Keyframe>

<Keyframe next="2480,233.858" anchor="0,233.858" previous="-1208,233.858" timevalue="15561" roving="1">

</Keyframe>

<Keyframe next="0,282.047" anchor="0,282.047" previous="-2480,330.21" timevalue="23000" roving="0">

</Keyframe>

</Property>

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Rotation_Z">

<Keyframe next="0,0" anchor="0,0" previous="0,0" timevalue="0" roving="0">

</Keyframe>

</Property>

</PropertyContainer>

<PropertyContainer id="Transformation">

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Skew_X">

<Keyframe next="0,0" anchor="0,0" previous="0,0" timevalue="0" roving="0">

</Keyframe>

</Property>

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Skew_Y">

<Keyframe next="0,0" anchor="0,0" previous="0,0" timevalue="0" roving="0">

</Keyframe>

</Property>

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Scale_X">

<Keyframe next="0,100" anchor="0,100" previous="0,100" timevalue="0" roving="0">

</Keyframe>

</Property>

<Property enabled="1" readonly="0" visible="1" ignoreTimeMap="0" TimeMapIndex="0" id="Scale_Y">

<Keyframe next="0,100" anchor="0,100" previous="0,100" timevalue="0" roving="0">

</Keyframe>

</Property>

</PropertyContainer>

<PropertyContainer id="Colors">

</PropertyContainer>

<PropertyContainer id="Filters">

</PropertyContainer>

</PropertyContainer>

</AnimationCore>

CutomMotionPresetApplied.PNG

Code for reading all app.motionPresets to the JavaScript console of the ESTK:

var doc = app.documents[0];

var appMotionPresets = app.motionPresets.everyItem().getElements();

var motionPresetsLength = appMotionPresets.length;

for( var n=0 ; n<motionPresetsLength; n++ )

{

    $.writeln(  n+" "+"**************************************"+"\r" );

    $.writeln(  appMotionPresets.contents.split("><").join(">\r<") );

};

Did not dig deeper into this…

You could manage your custom motion presets:

ManageCutomMotionPresets.PNG

FWIW: motion presets can be done also with the Adobe Flash app, stored as XML files and used with InDesign.

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 05, 2019 Jul 05, 2019

Copy link to clipboard

Copied

Found some documentation about the motion presets in XML form:

Motion XML Elements - Adobe ActionScript® 3 (AS3) API Reference

Not eaxctly the thing I was looking for. All for ActionScript 3 and not ExtendScript's motionPreset.contents for InDesign.

I hope there is more somewhere on the web that comes closer.

Regards,
Uwe

PS: EDITED

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 05, 2019 Jul 05, 2019

Copy link to clipboard

Copied

Hi friends,

Thanks a lot, you put me on the right track 🙂

Uwe:

1. The motion preset contents (XML) is not easy to decipher, but it obviously contains interesting data. What I found so far is that the "Basic_Motion" PropertyContainer tag owns something of a copy of the motion path, based on distinct (X, Y, Z) coordinates—Z for rotation! The Keyframe items are not our “green keyframe” points and don't even reflect the original path points as such. In fact, the motion preset creates its own control points with respect to TimeMap (I guess), but the resulting path perfectly fits the original. Anyway, what is useful here is that any X- and Y- keyframe's anchor is associated to a timevalue attribute. This somehow answers my original question, or at least this brings a good starting point before further calculations.

2. Much more, I incidentally discovered a hidden gem in the XML: the orientToPath attribute of the Settings tag, "0" by default. If you change it to "1" and reset the motion preset contents string, nothing seems to happen. In fact, a great thing happens under the hood: a rotationArray is automatically created in the animationSettings instance to compensate the effect of orientToPath changing! Crazy, isn't it? So, if you then reset the rotationArray to [ ], your target object now enjoys the orient-to-path dynamics. Well, that's a bit more complicated and buggy, but this is basically the feature I was looking after in my particular project. (I can not reveal more detail here, but you get the basic trick.)

Trevor:

Thanks to you too. The steps you describe are exactly what I was about to do: cubic math 😉 My idea was to compute each sublength (per Bezier curve) then to find the law that remaps any timestamp (normalized in 0..1) to a length (normalized in 0..1 as well). Since easing attributes are more-or-less Bezier-driven, I think it's possible to determinate such a map—like the “Warp” feature in Ableton Live. But, yes, Uwe's suggestion should save me from entering those hellish equations.

Best,

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 05, 2019 Jul 05, 2019

Copy link to clipboard

Copied

LATEST

Hi,

I did a load of stuff on this for our Baker Export ( which never took off ). You will be able to see the keyframes if you export your document using the demo script from here:

Mac CC 2018 only.

Baker Export - Kerntiff Publishing Systems

It was a fun project.

All the best.

P.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jul 04, 2019 Jul 04, 2019

Copy link to clipboard

Copied

Hi Marc,

For the example illustrated in your png the commutation would be comparatively simple.

One would divide the path into it's 3 Bezier curves and calculate the length of each curve.

Then one can compare the length ratios let's say for example the lengths of the curves are (0) 300, (1) 300 and (2) 400 = 1000

You are interested in (2) which is 600 from the start which would correspond to frame 24 * 600 / 1000 = 14.4 (purely coincidental that 14.4 roughly matches the value in the picture).

Calculating the tangent at that given point is also not so complicated.

This is fine for out overly simple case where the t (time) and l (length) of the curves have a linear relationship.

I have no doubt you know Pomax's repo by heart and the above would take you seconds.

The problem comes with the non liner relationships, ease in etc. they would make the task much more of a nightmare as one would have to calculate the values used for the effects.

The approach I would go for would be to export the document as an HTML document which one could examine much more easily than the InDesign document and perhaps have access to the ease in etc values.

Nothing particularly enlightening in the above and all I can do is wish you my sympathies with the job!

Trevor

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jul 04, 2019 Jul 04, 2019

Copy link to clipboard

Copied

I see Uwe found something nice!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines