Copy link to clipboard
Copied
My question is fairly simple but haven't found a good solution yet.
The image below shows all key-frames have been placed on a layer
I am wondering is there any ways that can quickly space out those dots evenly. like this image below:
I use photoshop / illustrator as well. they have a series of buttons like this:
Does After Effect has something similar tools like that as well? if not, how can i quickly achieve the evenly space out dots.
Thanks, Appreciated
Hi there, Use this Script.
function adjustKeyframeSpace() {
var selectedLayers = app.project.activeItem.selectedLayers;
if (selectedLayers.length == 0) {
alert("Please select a layer with keyframes to run this script");
return;
}
var selectedProperties = selectedLayers[0].selectedProperties;
if (selectedProperties.length == 0) {
alert("Please select a property with keyframes to run this script");
return;
}
var selectedKeyframes = selecte
...
Copy link to clipboard
Copied
Thankyou
This is a good workaround, I wish AE had an option to evenly space out keyframes in a given area. I downloaded rift plugin and I can't even work that plugin out!
Copy link to clipboard
Copied
Nice one, thank you! Staight answers.
Copy link to clipboard
Copied
Thank you, your video was very helpful!
Copy link to clipboard
Copied
yes its a workaround, but its just not an efficient method at all, its so simple, all the OP want to do was distribute keyframes evenly from the start to the end of his selection.. like you say, if your trying to manage many keyframes.. its a problem..
Copy link to clipboard
Copied
I've checked all the replies below and none answers his question.
does anyone know how to do it?
Copy link to clipboard
Copied
select your keyframes, right-click and select "Keyframe Interpolation", then choose "Linear" for both Temporal Interpolation & Spatial Interpolation.
 
i hope this helps 🙂
Copy link to clipboard
Copied
this does not space out keyframes.
Copy link to clipboard
Copied
Hello, it's far the best advice of the topic, but i have an issues. The spatial interpolation and roving appears grey and not editable, do you know why ?
Copy link to clipboard
Copied
A manual way is described in this thread: https://community.adobe.com/t5/after-effects-discussions/evenly-distribute-keyframes/m-p/13162845
Copy link to clipboard
Copied
Meanwhile I wrote an expression that has the same effect. Though not distributing the actual keyframe dots, it does distribute the values evenly when rendering. Thanks for inspiring me to do so 🙂
Still longing for a script that distributes the actual keyframes.
// Distribute keyframe values evenly (not the actual keyframes)
//
// Create markers at the Start and End times
// Create any number of keyframes, don't care about the exact timing
// Paste this expression in the property's expression field
// Expression by jaydude.nl / 2022
var mS = marker.key(1).time;
var mE = marker.key(2).time;
var kValue = [];
var n = numKeys;
var i;
for (i = 1; i < n + 1; i++) {
kValue[i] = valueAtTime(key(i).time);
};
k = Math.round(linear(time , mS , mE , 1 , n));
kValue[k];
Copy link to clipboard
Copied
I wanted a load of evenly spaced hold key frames with ascending position values. My work around is this:
1. create two key frames the required distance apart.
2. Create a null object. This will just be like a construction guide layer.
3. Select your two key frames and ctrl C to copy them.
4. Use the K key to move the play head exactly on the second keyframe and with the Null object selected Ctrl V to paste. Keep pressing K to shift the play head along and pasting until you have a guide layer of evenly distributed keyframes.
5. now on the layer you actually want keyframes you can use J and K to snap to your guides. And add your keyframes accordingly.
6. For the keyframe values I had to consider the maths but I put the equation in the value box. For example I wanted each hold keyframe to increase the X position by 200 pixels so I would add the keyframe and if the existing X value was 100 I would add "+200" in the little box, hit enter and it would be 300. The next KF I added would then also be 300 and I would "+200" to that. Etc.
7. You can delete the null layer if you don't need it anymore.
Its not automatic but it's precise and fairly painless.
Copy link to clipboard
Copied
Wow, I can't believe this is so complicated.
Copy link to clipboard
Copied
Hi there, Use this Script.
Copy link to clipboard
Copied
Hi there, Use this Script.
function adjustKeyframeSpace() {
var selectedLayers = app.project.activeItem.selectedLayers;
if (selectedLayers.length == 0) {
alert("Please select a layer with keyframes to run this script");
return;
}
var selectedProperties = selectedLayers[0].selectedProperties;
if (selectedProperties.length == 0) {
alert("Please select a property with keyframes to run this script");
return;
}
var selectedKeyframes = selectedProperties[0].selectedKeys;
if (selectedKeyframes.length == 0) {
alert("Please select some keyframes to run this script");
return;
}
var keyframeDuration = selectedProperties[0].keyTime(selectedKeyframes[selectedKeyframes.length - 1]) - selectedProperties[0].keyTime(selectedKeyframes[0]);
var keyframeInterval = keyframeDuration / (selectedKeyframes.length - 1);
for (var i = 0; i < selectedKeyframes.length; i++) {
var newKeyframeTime = selectedProperties[0].keyTime(selectedKeyframes[0]) + (keyframeInterval * i);
var easeIn = selectedProperties[0].keyInTemporalEase(selectedKeyframes[i])[0];
var easeOut = selectedProperties[0].keyOutTemporalEase(selectedKeyframes[i])[0];
var value = selectedProperties[0].valueAtTime(selectedProperties[0].keyTime(selectedKeyframes[i]), true);
selectedProperties[0].removeKey(selectedKeyframes[i]);
selectedProperties[0].setValueAtTime(newKeyframeTime,value);
selectedProperties[0].setTemporalEaseAtKey(1, [easeIn], [easeOut]);
}
}
adjustKeyframeSpace();
Copy link to clipboard
Copied
@Aryan244766988iej Thank you for writing this script!
Copy link to clipboard
Copied
Just what I need! In AE, I'm getting an error at line 13 "Undefined is not an object" when run.Not a strong coder, so I don't know how to fix it. Anyone else had that issue?
Copy link to clipboard
Copied
Same here.
Copy link to clipboard
Copied
Thanks for sharing anyway - maybe this wil evolve to a solution.
Copy link to clipboard
Copied
Thank you so much! God bless you!
Copy link to clipboard
Copied
I love the comparison to illustrator and would find this an extremly helpful keyboard shortcut or tool in the properties panel!
Copy link to clipboard
Copied
I created this script (with the help of Perplexity...):
{
function spaceOutSelectedKeyframesEvenly() {
var comp = app.project.activeItem;
if (!(comp && comp instanceof CompItem)) {
alert("Please select a composition.");
return;
}
var selectedLayers = comp.selectedLayers;
if (selectedLayers.length === 0) {
alert("Please select at least one layer.");
return;
}
// Find first property with selected keyframes
var targetProp = null;
for (var i = 0; i < selectedLayers.length; i++) {
var layer = selectedLayers[i];
var selectedProps = layer.selectedProperties;
for (var j = 0; j < selectedProps.length; j++) {
var prop = selectedProps[j];
if (prop.numKeys > 0 && prop.selectedKeys.length > 0) {
targetProp = prop;
break;
}
}
if (targetProp) break;
}
if (!targetProp) {
alert("Please select a property with selected keyframes.");
return;
}
var intervalFramesStr = prompt("Enter interval between keyframes in frames:", "5");
if (intervalFramesStr === null) return;
var intervalFrames = parseInt(intervalFramesStr, 10);
if (isNaN(intervalFrames) || intervalFrames <= 0) {
alert("Invalid interval entered. Please enter a positive integer.");
return;
}
app.beginUndoGroup("Space Out Selected Keyframes Evenly");
var frameDuration = 1 / comp.frameRate;
// Get selected keyframe indices sorted ascending
var selectedKeyIndices = targetProp.selectedKeys.slice(0).sort(function(a, b) { return a - b; });
// Save original keyframe data (time, value, easing, interpolation)
var keyData = [];
for (var i = 0; i < selectedKeyIndices.length; i++) {
var idx = selectedKeyIndices[i];
keyData.push({
originalTime: targetProp.keyTime(idx),
value: targetProp.keyValue(idx),
inInterp: targetProp.keyInInterpolationType(idx),
outInterp: targetProp.keyOutInterpolationType(idx),
temporalEaseIn: targetProp.keyInTemporalEase(idx),
temporalEaseOut: targetProp.keyOutTemporalEase(idx),
spatialInterp: (typeof targetProp.keySpatialInterpolationType === "function") ? targetProp.keySpatialInterpolationType(idx) : null,
roving: (typeof targetProp.keyRoving === "function") ? targetProp.keyRoving(idx) : false
});
}
// Calculate new times spaced evenly starting at the first selected keyframe's original time
var startTime = keyData[0].originalTime;
var newTimes = [];
for (var i = 0; i < keyData.length; i++) {
newTimes.push(startTime + i * intervalFrames * frameDuration);
}
// Remove selected keyframes from highest index to lowest to avoid reindexing issues
for (var i = selectedKeyIndices.length - 1; i >= 0; i--) {
targetProp.removeKey(selectedKeyIndices[i]);
}
// Add new keyframes at new evenly spaced times with original values and restore easing/interpolation
for (var i = 0; i < keyData.length; i++) {
targetProp.setValueAtTime(newTimes[i], keyData[i].value);
var newKeyIndex = targetProp.nearestKeyIndex(newTimes[i]);
if (newKeyIndex > 0) {
targetProp.setTemporalEaseAtKey(newKeyIndex, keyData[i].temporalEaseIn, keyData[i].temporalEaseOut);
targetProp.setInterpolationTypeAtKey(newKeyIndex, keyData[i].inInterp, keyData[i].outInterp);
if (keyData[i].spatialInterp !== null) {
targetProp.setSpatialInterpolationTypeAtKey(newKeyIndex, keyData[i].spatialInterp);
}
if (keyData[i].roving !== undefined) {
targetProp.setRovingAtKey(newKeyIndex, keyData[i].roving);
}
}
}
app.endUndoGroup();
}
spaceOutSelectedKeyframesEvenly();
}
Find more inspiration, events, and resources on the new Adobe Community
Explore Now