<p>Is there any reason why you're using this approach? There are <em>far</em> easier ways to do it (see below). </p>

<p>But anyway the problem is that the second last and last line both return values, but an expression can only return one set of values, and so it only returns the last one. I think this points to a misunderstanding of how expressions work. An expression is calculated every frame*; it has no memory of what happened previously or what will happen later. So your expression has to return one result for any particular point in time, and the result is calculated from the value it returns at that time.</p>

<p>You need some flow control there. Use an <code>if/else</code> statement to replace the last two lines:</p>

<pre class="lang-js prettyprint-override"><code>if (time &lt; mid1){
    [linear(time, start1, mid1, 640, effect("End Position")("Point")[0]), linear(time, start1, mid1, 360, effect("End Position")("Point")[1])];
}else{
    [linear(time, mid1, end1, effect("End Position")("Point")[0], 640), linear(time, mid1, end1, effect("End Position")("Point")[1], 360)];
}
</code></pre>

<p>But you can make your life a <em>lot</em> easier. Why not have a slider effect that has a 0-100 range that defines what percentage of the distance along the path the object should be at. Then you just keyframe it to ramp from 0-100 and back again. The <strong>whole</strong> expression would just be:</p>

<pre class="lang-js prettyprint-override"><code>rampCtrl=effect("the Effect That Controls How Far Along It is")("slider");
linear(rampCtrl, 0, 100, [640,360], effect("End Position")("Point"))
</code></pre>

<p>Note that you don't have to split it into two parts, the <code>linear()</code> function can deal with vectors as the value1 and value2 inputs.
<hr>
*(you can think of expressions as being calculated every frame, but they are actually calcualted every time the comp is rendered. If you have motion blur on, the frame is composed of numerous time slices at sub-frame points in time, blended together, and the expression is calculated for each of those time slices. Generally you can ignore this, but it does impact rendering speed if your calcualtion is <em>very</em> time consuming, and it can cause weirdness if your expression returns unexpected results between frames, e.g. when looping back to an original value between two frames)</p>

CC BY-SA 3.0
2016-08-17T06:49:26.043Z
Thanks so much for the help. I have only been messing with expressions for a week or so, but now I have a better understanding of how the expression logic works. 

I'll also try using your version and see if it makes it any easier for me.
user16421
CC BY-SA 3.0
2016-08-16T15:25:56.417Z
2016-08-17T07:54:46.670Z
2016-08-17T07:54:46.670Z
stib
<p>Essentially I am trying to get a position expression on a video layer (two dimensional) to go from 640, 360 (middle of the screen) to another value defined by an expression control and then back to 640, 360. To define the duration of this effect I have used placeholder checkboxes (start, middle and end) to create drag-able keyframes that mark the start and end points. I know this is a strange way to define the start and end points of the effect, but it works well for what I'm doing.</p>

<p>Current code:</p>

<pre class="lang-js prettyprint-override"><code>start = effect("Start (use keyframe)")("Checkbox");
end = effect("End (use keyframe)")("Checkbox");
mid = effect("Middle (use keyframe)")("Checkbox");

if (start.numKeys &gt; 0){
start1 = start.key(start.numKeys).time
}
else{
start1 = 0;
}

if (end.numKeys &gt; 0){
end1 = end.key(end.numKeys).time;
}
else{
end1 = 0;
}

if (mid.numKeys &gt; 0){
mid1 = mid.key(mid.numKeys).time;
}
else{
mid1 = 0;
}

[linear(time, start1, mid1, 640, effect("End Position")("Point")[0]), linear(time, start1, mid1, 360, effect("End Position")("Point")[1])];

[linear(time, mid1, end1, effect("End Position")("Point")[0], 640), linear(time, mid1, end1, effect("End Position")("Point")[1], 360)];
</code></pre>

<p>Note: the code has worked fine without the mid variable and the second linear expression, however it won't go from 640, 360 to x, y and then back to 640, 360. It will only go from 640, 360 to x, y and then stop.</p>

<p>I have also tried using the loopOut("pingpong") function but it breaks the entire expression.</p>

<after-effects><after-effects-expressions>
After Effects: Linear Expression - going from value 1 to another value and then back to value 1
user16421
# After Effects: Linear Expression - going from value 1 to another value and then back to value 1

(Asked by: username_0 on 2016-08-16)

Essentially I am trying to get a position expression on a video layer (two dimensional) to go from 640, 360 (middle of the screen) to another value defined by an expression control and then back to 640, 360. To define the duration of this effect I have used placeholder checkboxes (start, middle and end) to create drag-able keyframes that mark the start and end points. I know this is a strange way to define the start and end points of the effect, but it works well for what I'm doing.
Current code:
start = effect("Start (use keyframe)")("Checkbox");
end = effect("End (use keyframe)")("Checkbox");
mid = effect("Middle (use keyframe)")("Checkbox");

if (start.numKeys > 0){
start1 = start.key(start.numKeys).time
}
else{
start1 = 0;
}

if (end.numKeys > 0){
end1 = end.key(end.numKeys).time;
}
else{
end1 = 0;
}

if (mid.numKeys > 0){
mid1 = mid.key(mid.numKeys).time;
}
else{
mid1 = 0;
}

[linear(time, start1, mid1, 640, effect("End Position")("Point")[0]), linear(time, start1, mid1, 360, effect("End Position")("Point")[1])];

[linear(time, mid1, end1, effect("End Position")("Point")[0], 640), linear(time, mid1, end1, effect("End Position")("Point")[1], 360)];

Note: the code has worked fine without the mid variable and the second linear expression, however it won't go from 640, 360 to x, y and then back to 640, 360. It will only go from 640, 360 to x, y and then stop.
I have also tried using the loopOut("pingpong") function but it breaks the entire expression.

**Tags:** after-effects, after-effects-expressions


---

## 1 answers

### Answer by username_1 on 2016-08-16. Score: 1 | Accepted answer

Is there any reason why you're using this approach? There are far easier ways to do it (see below). 
But anyway the problem is that the second last and last line both return values, but an expression can only return one set of values, and so it only returns the last one. I think this points to a misunderstanding of how expressions work. An expression is calculated every frame*; it has no memory of what happened previously or what will happen later. So your expression has to return one result for any particular point in time, and the result is calculated from the value it returns at that time.
You need some flow control there. Use an if/else statement to replace the last two lines:
if (time < mid1){
    [linear(time, start1, mid1, 640, effect("End Position")("Point")[0]), linear(time, start1, mid1, 360, effect("End Position")("Point")[1])];
}else{
    [linear(time, mid1, end1, effect("End Position")("Point")[0], 640), linear(time, mid1, end1, effect("End Position")("Point")[1], 360)];
}

But you can make your life a lot easier. Why not have a slider effect that has a 0-100 range that defines what percentage of the distance along the path the object should be at. Then you just keyframe it to ramp from 0-100 and back again. The whole expression would just be:
rampCtrl=effect("the Effect That Controls How Far Along It is")("slider");
linear(rampCtrl, 0, 100, [640,360], effect("End Position")("Point"))

Note that you don't have to split it into two parts, the linear() function can deal with vectors as the value1 and value2 inputs.

*(you can think of expressions as being calculated every frame, but they are actually calcualted every time the comp is rendered. If you have motion blur on, the frame is composed of numerous time slices at sub-frame points in time, blended together, and the expression is calculated for each of those time slices. Generally you can ignore this, but it does impact rendering speed if your calcualtion is very time consuming, and it can cause weirdness if your expression returns unexpected results between frames, e.g. when looping back to an original value between two frames)

> **Comments:**
> **username_0**: Thanks so much for the help. I have only been messing with expressions for a week or so, but now I have a better understanding of how the expression logic works.   I'll also try using your version and see if it makes it any easier for me.  

---

