# Animating In & Animate Out

We still have to handle the remaining play out commands executed by CasparCG. To begin, we are going to add two more functions to our graphic, `animateIn` and `animateOut`.

```javascript
'use strict';

// lower-third.1.js

const _graphic = (function() {

    /* Update Function */
    function animateIn() { }
    function play() { }
    function next() { }
    function animateOut() { }
    function stop() { }
    function remove() { }

    function handleError(e) {console.error(e)}
    function handleWarning(w) {console.log(w)}
    return { }

})();
```

### Handle the Play Command

Let's handle the `play` function first. First we want to make sure the graphic is in the correct state. If it is, we can call `animateIn` and increment the state to `2`.

```javascript
function animateIn() { }

function play() {
    // State 1 means graphic is loaded and ready to be played
    if(state === 1) {
        animateIn();
        state = 2;
    }
}

function next() { }
```

### Animating In

#### Setting up the Variables

Our `animateIn` function will be similar to the `applyStyles` and `applyData` functions. We will begin by getting a reference to all the elements that will be animated.&#x20;

```javascript
/* Update Function */
function animateIn() {
    const graphic = document.querySelector('.lt-style-one .graphic');
    const [pathLeft, pathRight] = graphic.querySelectorAll('svg path');
    const title = graphic.querySelector('h1');
    const subtitleCon = graphic.querySelector('.subtitle');
    const subtitle = subtitleCon.querySelector('p');
}
/* Play Function */
```

We will use the [deconstructing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) trick with the SVG `path`s again. Then have to address some scaling issues with our SVG `path`s.

#### Dynamic Stroke Length w/ Dash Array & Dash Offset

The [`strokeDasharray`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray) and [`strokeDashoffset`](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset) are two new properties for SVG `path` elements. The `strokeDasharray` property breaks our path's stroke into mini segments while the `strokeDashoffset` offsets the path's stroke. Combining these two properties together will give you an animation that looks like the paths are being "drawn onto" the screen. We are going to want to allow the graphic to change size dynamically based on the length of the `h1` element. This means the value used for `strokeDasharray` and `strokeDashoffset` will very based on the `.graphic` element's size.&#x20;

At first glance it may look like `graphic.style.width` would be the easy answer but, this value is and empty string due to the `width` being set by the style sheet. We can use two functions called `getComputedStyle` and `getPropertyValue` to get the `width` the browser is using. Let's start with an example.

```javascript
/* Example */
const elem = document.querySelector('body');
const computedStyles = window.getComputedStyle(elem);
const width = computedStyles.getPropertyValue('width');
```

The function `getComputedStyle`  takes one argument and that is a DOM element. It then returns the styles set by the CSS style sheet and browser. From there, we call `getPropertyValue` on the `computedStyles`. It takes one argument and it can be any CSS value we want to know. We could get the `width` of the `.graphic` element in our `animateIn` function, but to make it more versatile, we are going to write a separate function that can be used in a variety of situations.&#x20;

```javascript
// Gets the CSS values used by the browser
// @param {DOM Node} elem - The element whos styles you want
// @param {string | string[]} styles - The CSS properties needed
// @returns {any[]} An array of strings and/or numbers
function getComputedStyle(elem, styles) {
    // Get the element's computed styles
    const computedStyles = window.getComputedStyle(elem);
    // Create an array to hold the requested results
    const values = [];
    if(Array.isArray(styles)) {
        // Loop over each style requested and all the value to the result
        styles.forEach(s => 
            values.push(computedStyles.getPropertyValue(s)));
    } else {
        values.push(computedStyles.getPropertyValue(styles));
    }
    return values.map(v => {
        // Clean up pixel values
        if(v.includes('px')) v = Number(v.substring(0, v.length - 2));
        return v;
    });
}

function animateIn() {
    const graphic = document.querySelector('.lt-style-one .graphic');
    const [pathLeft, pathRight] = graphic.querySelectorAll('svg path');
     /* Other Element Variable Definitions */
    
    // Request the .graphic elements width
    const graphicWidth = getComputedStyle(graphic, 'width')[0];
    // Our path wraps around our graphic making 
    // it's path width about twice as big
    const pathWidth = graphicWidth * 2; 
}
```

This `getComputedStyles` function allows us to pass in an element and either an CSS property or an array of CSS properties and get them back as an array of values.&#x20;

#### Animating In

Now that we have our dynamic width, we can animate the graphic in!

```javascript
function animateIn() {
    /* Element Variable Definitions */
    
    const tl = new gsap.timeline({duration: 1, ease: 'power1.out'});
    tl.set([pathLeft, pathRight], {
            strokeDashoffset: pathWidth, 
            strokeDasharray: pathWidth 
        }).set(title, {y: '15vh'})
        .set(subtitleCon, {y: '10vh'})
        .set(subtitle, {y: '20vh'})
        // Reveal the graphic
        .set(graphic, {opacity: 1})
        // Animation Begins
        .to([pathLeft, pathRight], {
            strokeDashoffset: 0, 
            duration: 1.5 // Overides the default duration
        }).to(title, {y: 0}, '-=1')
        .to(subtitleCon, {y: 0}, '-=.9')
        .to(subtitle, {y: 0}, '-=1');
}
```

We haven't seen the `set` function yet but, it simple changes the values instantly, instead of animating them over time. If we save the JS file, refresh the browser or reload Caspar, run `update` with our data, and then run `play` we should see our graphic animate in.&#x20;

### Handling the Stop Command

Creating the `stop` function is very similar to the `play` function but we will check for state `2` instead.

```javascript
function animateOut() { }

function stop() {
    // State 2 means graphic is played and ready to be stopped
    if(state === 2) {
        animateOut();
        state = 1;
    }
}

function remove() { }
```

### Animating Out

Animating in was the majority of the work since an animation out, is typically the same animation in but backwards. Let's reorder the `animateIn` function and change some values to get out `animateOut` function.

```javascript
function animateOut() {
    /* The same vas the animateIn function */
    const graphic = document.querySelector('.lt-style-one .graphic');
    const [pathLeft, pathRight] = graphic.querySelectorAll('svg path');
    const title = graphic.querySelector('h1');
    const subtitleCon = graphic.querySelector('.subtitle');
    const subtitle = subtitleCon.querySelector('p');
    const titleWidgth = getComputedStyle(graphic, 'width')[0];
    const pathLength = titleWidgth * 2;
    
    const tl = new gsap.timeline({duration: 1, ease: 'power1.in'});
    tl.to(title, {y: '15vh'})
        .to(subtitleCon, {y: '10vh'}, '-=.75')
        .to(subtitle, {y: '20vh'}, '-=.55')
        .to([pathLeft, pathRight], {
            strokeDashoffset: pathLength, 
            ease: 'power1.inOut', 
            duration: 2
        }, '-=1')
        .to(graphic, {opacity: 0}, '-=.25');
}
```

The animate out value's are the values used for the `set` function in the animation in. Feel free to play around with the properties until you find an animation you prefer.

#### Resources

* [Stroke Dash Array](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray) on MDN's website.
* [Stroke Dash Offset](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset) on MDN's website.
* [Get Computed Styles](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle) on MDN's website.
* [Get Property Value](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue) on MDN's website.
* [Set ](https://greensock.com/docs/v3/GSAP/gsap.to\(\))on GreenSock's website.
* [To ](https://greensock.com/docs/v3/GSAP/gsap.to\(\))on Greensock's website.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chrisryanouellette.gitbook.io/casparcg-html-template-guide/javascript/animating-w-gsap-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
