Search code examples
javascriptjquerycssanimationgsap

Accessing updated CSS values from previously animated elements in a Greensock timeline


I have a TimelineLite() which performs a series of .to() tweens in sequential order. I'd like to be able to use the value that results from one of the early tweens in the construction of one of the later tweens.

Is there anyway to access the values of elements that have previously completed their animation in a timeline?

UPDATED:

The example that I provided originally was quite crude. I've updated it to more accurately reflect what I'm running into.

The size of the colored div are dependent on the viewport, and the content within them flows based on that size. Clicking on one of them begins an animation which expands the clicked div to fill the viewport and removes the non-clicked divs. This resizing causes the text to reflow to adjust for the new space.

Then div.status (that was previously absolutely positioned off the bottom of the page) animates up to be below the selected colored div. Unfortunately, the height that is used to calculate its new top value is what the selected colored div's height was prior to the animation and subsequent reflow of it's content.

var timeline = new TimelineLite();

$('.clickable').click(function(){
  var $selected = $(this);
  var $notSelected = $('.clickable').not($(this));
  $selected.addClass('selected');
  $notSelected.addClass('not-selected');
  
  timeline
  .add("optionSelected")
  .to(
    $selected,
    0.5,
    { "width":"96%" },
    "optionSelected"
  )
  .to(
    $notSelected,
    0.5,
    {
      "width":"0%",
      "padding":"0"
    },
    "optionSelected"
  )
  .to(
    $(".status"),
    0.5,
    {
      "top":$('.selected').height()
    }
  )
})
body{
  position:relative;
  height:100vh;
  overflow:hidden;
  background-color:cornsilk;
}
section{
  background-color:#ddd;
  display:flex;
  align-items: flex-start;
}
div{
  width: 30%;
  padding:2%;
  color: #FFF;
  display:inline-block;
}
.clickable{cursor:pointer;}
.status{
  width:96%;
  position:absolute;
  top:100%;
  left:0;
  background-color:#FFF;
  color:black;
  border:1px solid black;
}
.blue{background-color:blue;}
.green{background-color:green;}
.purple{background-color:purple;}
.not-selected{ 
  white-space: nowrap;
  overflow:hidden;
}
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <section>
    <div class="blue clickable"><strong>Clickable</strong> - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Dignissim tortor, sit amet vulputate augue lectus vel felis. Cras ac ex vel ligula porta laoreet. 
    </div>
    <div class="green clickable"><strong>Clickable</strong> - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultrices, est ut sollicitudin gravida, velit erat dignissim tortor, sit amet vulputate augue lectus vel felis. Cras ac ex vel ligula porta laoreet. Mauris lorem tellus, convallis ac tincidunt eu, efficitur consequat turpis.</div>
    <div class="purple clickable"><strong>Clickable</strong> - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultrices, est ut sollicitudin gravida, velit erat dignissim tortor, sit amet vulputate augue lectus vel felis. Cras ac ex vel ligula porta laoreet.</div>

    <div class="status">Status</div>
  </section>
</body>


Solution

  • Try returning the desired height from a function as a callback. I think then it won't be executed until after the animation of the .selected element has reached that to() in the chain.

    Also height() does not include padding or margins, so you end up with the .status overlapping, try .outerHeight() instead.

    Working example:

    http://codepen.io/jonwheeler/pen/jAvRZZ?editors=0110