David Conklin
Forum Replies Created
-
Hey Ryan,
I’m having a hard time following what you’re going for this time, but here’s what I’ve got. Hopefully it will put you on the right track:
This expression will go from 0 to 11.111 during the time between keyframes 1 and 2, hold at 11.111 between keyframe 2 and 3, and then go from 11.111 to 50 between keyframe 3 and 4. Of course, 50 is an arbitrary number I made up, so feel free to change it.
This expression now is not ‘mapping’ the position of your box to this slider, but rather creating slider values that correspond w/ the time of your keyframes. Meaning, the slider value is 0 up until the first keyframe, regardless of where the box is on screen (same for all other slider values).
Let me know if this works, otherwise perhaps you could give me a little more detail on what you’re trying to accomplish.
Good luck,
//this goes on the slider
//change this to the layer of your box
var cntrl = thisComp.layer(“BOX”);//this is the property we’re tracking
var getProp = cntrl.transform.position;//set slider values
var valAtStart = 0; //keyframe 1
var valAtHold = 11.111; //keyframe 2 + 3
var valAtEnd = 50; //keyframe 4.//make sure we have at least 4 keyframes.
if(getProp.numKeys >= 4){//get time of keyframes
var key1Time = getProp.key(1).time;
var key2Time = getProp.key(2).time;
var key3Time = getProp.key(3).time;
var key4Time = getProp.key(4).time;//make animations
var animOn = ease(time, key1Time, key2Time, valAtStart, valAtHold);
var animOff = ease(time, key3Time, key4Time, valAtHold, valAtEnd);//apply animation
if (time < key1Time){ valAtStart; } else if (time < key2Time){ animOn; } else if (time < key3Time){ valAtHold; } else if (time < key4Time){ animOff; } else { valAtEnd; } } else { //just use slider value if there's less //than 4 keyframes. This will prevent //error dialog spam if you delete //keyframes. value; } David Conklin Motion Designer -
Dan’s answer is entirely correct, but maybe this can help you understand some of the math involved.
—
Using simple trigonometry:
Imagine you have the point [960, 540];
Those 2 values, 960 and 540, represent two adjacent sides of a triangle.
Now, if you recall back to 9th Grade, you may remember that there is a simple equation to get the third side of that triangle. A² + B² = C². So, we can find the third side (the magnitude) by using an equation like:
var mag = Math.sqrt(Math.exp(position[0], 2) + Math.exp(position[1], 2));
Essentially saying take the square root of X² + Y².Fortunately, AE gives us the handy little ‘length’ operator, which simply does all of these computations for us.
—
Another similar equation can be used to find the angle of a triangle when you know two other sides, you may remember SOH CAH TOA.
Imagine the angle at the top left of your comp, now notice that you have the opposite side (the Y coord) and the adjacent side (the X coord). Since TOA uses both opposite and adjacent sides, we can get that angle using an equation like this:
tan(theta) = opposite/adjacent
tan(theta) = 540/960
theta = tan−1(5625)or, in code
var angle = Math.atan(position[1] / position[0]);since this will return a value in radians instead of degrees, we need to convert it.
var angle_deg = radiansToDegrees(angle);—
As mentioned above, the code Dan posted in the previous post will do you just fine. I just find it helpful to visualize the math when approaching coding problems – especially those involving geometry/trig.
Good luck!
David Conklin
Motion Designer -
the [0] part (as in cntrl[0] or position[0]) is what’s picking out the X values. The position parameter is actually an array with 3 positions [x, y, z]. Since in javascript the first index of an array is 0, the values 0, 1 and 2 correspond to X, Y and Z respectively.
so,
position[0] = X Position
position[1] = Y Position
position[2] = Z PositionSimply change any/all [0]s to [1]s in order to use Y instead of X.
David Conklin
Motion Designer -
Heya – this expression is getting its data from the X position, yeah, but it’s still using an interpolation function to do so.
var makeSlider = linear(cntrl, boxStartX, boxEndX, sliderStart, sliderEnd);
While the default easing settings for this function are somewhat limited, you can do a regular easy-ease, ease-in or ease-out simply by changing the above line to something like this:
var makeSlider = ease(cntrl, boxStartX, boxEndX, sliderStart, sliderEnd);
var makeSlider = easeOut(cntrl, boxStartX, boxEndX, sliderStart, sliderEnd);
var makeSlider = easeIn(cntrl, boxStartX, boxEndX, sliderStart, sliderEnd);
Keep in mind that the expression is tracking the box’s progress as it moves between two points. This means that the easing applied to your box is already being applied to the slider. You could try to more heavily ease the box animation if you need a more eased slider. Using one of the ease() functions above will strengthen the ease applied to the slider, though.
Good luck!
David Conklin
Motion Designer -
David Conklin
November 24, 2014 at 6:10 pm in reply to: Creating an expression to correspond with an moving object, and live change of X,Y,Z valuesThe simplest answer, I think, is to simply choose a number by which to multiply your position values. For instance, if your layer rests at [960, 540, 100], simply multiplying those values by 10 would give you [9600, 5400, 1000].
I’m including an expression which would do this for you. I’m also writing in a ‘clamp’, so that values don’t exceed 10,000 or go below -10,000. You could, of course, alter this to fit your purposes.
The ‘scaler’ value can also be made into values less than 1 (i.e. .4 or 1/8) to make smaller values. I’ve also taken the liberty of removing the decimals for you using Math.floor (as you had done), but if you’d like decimals feel free to remove that code.
This expression assumes that the thing you’re tracking is called ‘satellite’ and is in the same comp as your text, you can change the expression to fit your needs if this does not work in your situation.
Hope this is helpful, happy expression-ing!
//this goes on source text of
//a text layer.//get the thing we're dealing with
var cntrl = thisComp.layer("satellite")//get positions of said thing
var xPos = cntrl.transform.position[0];
var yPos = cntrl.transform.position[1];
var zPos = cntrl.transform.position[2];//make a scaler value to amplify values
var scaler = 10;//value caps.
//set these to values you don't want
//to go above/below.
var maxVal = 100000;
var minVal = -100000;//multiply, but make sure we don't
//go outside of our range.
var xPos_make = Math.floor(Math.min(Math.max(xPos * scaler, minVal), maxVal));
var yPos_make = Math.floor(Math.min(Math.max(yPos * scaler, minVal), maxVal));
var zPos_make = Math.floor(Math.min(Math.max(zPos * scaler, minVal), maxVal));//make the string
"X: " + xPos_make + "metres" + "\r\n" +
"Y: " + yPos_make + "metres" + "\r\n" +
"Z: " + zPos_make + "metres" + "\r\n"David Conklin
Motion Designer -
Another trick would be to link the boxEndX variable to the last keyframe of your box’s position value, that way you don’t have to change the expression if you decide to redo the box animation. The expression is a little different, and would look like this:
//this goes on your slider.//get the thing we're tracking.
var cntrl = thisComp.layer("BOX").transform.position;//define holders
var boxStartX;
var boxEndX;//check to make sure there are keyframes
if(cntrl.numKeys > 0){
//get keyframe values.
boxStartX = cntrl.key(1).value[0];
boxEndX = cntrl.key(cntrl.numKeys).value[0];
} else {
//if no keyframes, fall back on these values
//(change them to whatever you need.)
boxStartX = 0;
boxEndX = 500;
}//slider values
var sliderStart = 0;
var sliderEnd = 11.1111;//make the interpolation.
var makeSlider = linear(cntrl[0], boxStartX, boxEndX, sliderStart, sliderEnd);Math.min(Math.max(sliderStart, makeSlider), sliderEnd);
The clamp is only necessary in case you have a/some middle keyframe(s) that go outside of the range set by your first and last keyframes.
Good luck!
David Conklin
Motion Designer -
Yeah, no problem. The line you’re looking for is this:
var boxEndX = thisComp.width //box ends at width of comp.
Simply change that to your box’s end X position and you should be good! For instance
var boxEndX = 985; //box ends at X=985.
Good luck!
David Conklin
Motion Designer -
You can use linear interpolation to do this. Essentially ‘mapping’ the X-val of your Box to the slider. What this does, basically, is say when Box is at position 0, slider should be 0, when box is at thisComp.width, slider is 11.1111. The beauty of this expression is that it ‘tweens’ all the values between those two states.
The last line of this expression simply makes sure that the slider never exceeds 11.1111 or goes below 0 (which may happen if your box goes into negative or past the width of your comp).
Of course, you can update all of these values to fit your case sepecifically.
Check out the below expression. Happy coding!
//this goes on your slider.//get the thing we're tracking.
var cntrl = thisComp.layer("BOX").transform.position[0];var boxStartX = 0 //box starts at 0;
var boxEndX = thisComp.width //box ends at width of comp.var sliderStart = 0; //slider begins at 0.
var sliderEnd = 11.1111; //slider ends at 11.1111.//make the interpolation.
var makeSlider = linear(cntrl, boxStartX, boxEndX, sliderStart, sliderEnd);//clamp the value (don't let it go out of range)
Math.min(Math.max(sliderStart, makeSlider), sliderEnd)David Conklin
Motion Designer -
Assuming your footage comp is named ‘ftg’ and the footage is the only layer inside that comp, you can access that layer’s properties using the following code:
var getFtg = comp("ftg").layer(1);
You can then do getFtg.whatever to get the data that you need. For instance:
//get the layer Name
var theName = getFtg.name;//duration of layer (secs)
var getDurSecs = getFtg.source.duration;//duration of layer (frames)
var getDurFrames = getFtg.source.duration * getFtg.source.frameDuration;//frame rate of ftg
var getFrameRate = 1/getFtg.source.frameDuration
Once you have the info you want, you can combine them into a string. You can use the characters “\r\n” to force a line break if you’d like:
"Footage Name: " + theName + "\r\n" +
"Footage FrameCount: " + getDurFrames + "\r\n" +
"Footage Frame Rate: " + getFrameRate + "fps" + "\r\n";
Hope this is what you were looking for. Good luck!
David Conklin
Motion Designer -
You may be overcomplicating it. If I’m gathering correctly, you just want each layer of a comp to be progressively linear wiped. You can use each layer’s index property as a way to offset these wipes.
I made a null called “Controls” in my comp and placed 2 sliders on it – one called ‘delay’ which I set to 30(frames) and one called ‘trans_time’ which I also set to 30(frames). I then created a bunch of solids in the comp and placed a linear wipe with this expression on the ‘transition completion’ property on each of them.
I am also attaching a project file so you can see how this looks. Let me know if this is what you were looking for.
Edit: Something interesting here, as well, is that you can make the delay value negative in order to make the transitions overlap.
var delay = thisComp.layer("Controls").effect("delay")("Slider") * thisComp.frameDuration; //convert to frames
var trans_time = thisComp.layer("Controls").effect("trans_time")("Slider") * thisComp.frameDuration; //convert to frames
var idx = index - 2; //to make the first solid 0 (to compensate for null and index starting at 1);var beginTime = (trans_time * idx) + (delay * idx); //make start time
var endTime = beginTime + trans_time; //make end timelinear(time, beginTime, endTime, 0, 100);