Updates

Just Animate 2.5.0

September 22th 2017

Live Updates

In this release Just Animate can now detect when new animations are added to a timeline and start animating them immediately! This means it is now possible to append to an active set of animations without needing to cancel and restart them.

Bugfix for a memory leak

If a timeline played for over 5 minutes, the performance of the web page degraded due to a memory leak in the memoize function. This has been fixed in this release.

Just Animate 2.4.0

September 14th 2017

Staggering Bugfix on CSS Selectors

In this release, an issue with staggering introduced in 2.3.0 has been resolved. Staggered targets resolved by CSS selectors were resolving the wrong starting time. This has been corrected and unit tests have been added to ensure this use case will work going forward.

Destroy and the Centralized State

A big change in this version is the introduction of centralized state and the destroy() function. The motive behind centralized state management is to further the goal of having a live keyframe editor extension for Chrome and FireFox. This is just another step toward making animation easier in the browser. The destroy() function was added to dispose of this state when finished with the timeline. For convenience, an additional play option has been added:

var t1 = just.animate(...)

t1.play({ destroy: true })

When destroy is true in the play options, it will automatically destroy the timeline the first time the timeline finishes.

Once Upon an Event

In this release, once() has been added to the timeline to make it convenient to handle a timeline event only one time. This can be especially useful when a timeline needs different playback options on subsequent plays.

Just Animate 2.3.0

September 3rd, 2017

Added References to Timeline

In this release, a new concept has been added to make refactoring even easier. Property functions, targets, and even easings can be defined when the timeline is created and then referenced by using the @ symbol. Consider the following code:

var t1 = timeline({
    references: {
        myTarget: '.css-selector',
        myEasing: 'cubic-bezier(0,0,1,1)',
        myValue: 2000
    }
})

t1.add({
    targets: '@myTarget',
    easing: '@myEasing',
    props: {
        x: [0, '@myValue']
    }
})

t1.play()

This feature makes it simple to swap out repeated values in the timeline making refactoring very easy.

Added animate() and sequence() to the Timeline

The animate() and sequence() functions have been added to the timeline for convenience. The animate() function is interchangable with add(), and the sequence() function makes it simple to add a sequence to the end of a timeline. The following code adds a sequence in the middle of a timeline.

var t1 = just.timeline({
    references: {
        target2: '.my-class-2'
    }
})

t1.animate({
    targets: '.my-class-1',
    duration: 1500,
    ...
})

t1.sequence([
    {
        targets: '@target2',
        duration: 500,
        ...
    },
    {
        targets: '@target2',
        duration: 500,
        ...
    },
    {
        targets: '@target2',
        duration: 500,
        ...
    }
])

t1.play()

Here is a working example and template to get started: Rubber Balls (Template)

Improved Timeline

The timeline's notion of active/inactive has been improved.

The timeline is inactive to start and after cancel() is called. The timeline is considered active as soon as play(), pause(), or finish() are called.

In the previous version things like resolving targets happened during the inactive phase. This has been changed to occur during the active phase only to allow a timeline to be canceled and reused. One consequence of this during staggering is that the duration in the inactive phase will only reflect the first item. This is a slight change in behavior for staggering as subsequent add() calls will not be at the end of staggering, but instead occur after the first item changes.

Just Animate 2.2.0

August 14th, 2017

Interpolate All the Things!

In this release, libraries like Flubber can be used plug and play in this new property. The following code uses Flubber to morph SVG from one shape to another.

var charmanderPath = ...;
var charmeleonPath = ...;

var t1 = just.animate({
    targets: '.charmander path',
    duration: 6000,
    props: {
        d: {
            value: [charmanderPath, charmeleonPath],
            interpolate: flubber.interpolate
        }
    }
})

t1.play()

The interpolate property instructs Just Animate on how to get continous values between each keyframe. You can even use interpolate to animate viewBox. The following code has a custom interpolator for viewBox that parses the left and right keyframes, and then returns a function to return intermediate values at a given offset (0 - 1 representing 0% to 100%).

var t1 = just.animate({
    targets: '.my-svg',
    duration: 1000,
    props: {
        viewBox: {
            value: ['0 0 800 600', '-200 200 800 600'],
            interpolate: interpolateViewBox
        }
    }
})

function interpolateViewBox(left, right) {
   var leftVal = left.split(' ').map(s => +s);
   var rightVal = right.split(' ').map(s => +s);

   return offset => {
      var vals = leftVal.map((l, i) => Math.round(just.interpolate(l, rightVal[i], offset)));
      return vals.join(' ');
   };
}

Just Animate 2.1.0

August 10th, 2017

This update contains some developer experience updates and bugfixes.

Added set() to... Set Things

In this release, set() has been added to the timeline. This function adds values to the timeline at the end of the timeline. The at property can be used to choose a different position if the end of the timeline isn't desired. If at is after the end of the timeline, it will automatically expand the timeline to that point. For instance, the following code can be used to set the initial value for transformOrigin.

var t1 = just.timeline()

t1.set({
    targets: '.my-element',
    web: { transformOrigin: 'center center' }
})

t1.set({
    at: 1000,
    targets: '.my-element',
    web: { transformOrigin: '0% 0%' }
})

In that example, the timeline's duration would be increased to 1000ms. The set() function can also be passed an array to set multiple things in one function call

Expanded add() and fromTo()

To improve the experience with add() and fromTo(), they were expanded to accept an array of animation options as well.

fromTo()

With fromTo() this helps because you can adjust the times for three animations without having to adjust the from and to values three times. Consider the following code differences

Last Version

var t1 = just.timeline()

t1.fromTo(0, 1000, {
    targets: '.target1',
    ...
})
t1.fromTo(0, 1000, {
    targets: '.target2',
    ...
})
t1.fromTo(0, 1000, {
    targets: '.target3',
    ...
})

This Version

var t1 = just.timeline()

t1.fromTo(0, 1000, [
    {
        targets: '.target1',
        ...
    },
    {
        targets: '.target2',
        ...
    },
    {
        targets: '.target3',
        ...
    }
])

add()

With add(), an array helps because the starting point for all options passed at the same time is the same. In other words, the following code would have required fromTo() in the previous version because target2 and target3 occur at the same time:

var t1 = just.timeline()

t1.add({
    targets: '.target1',
    duration: 1000,
    ...
})

t1.add([
    {
        targets: '.target2',
        duration: 1000,
        ...
    },
    {
        targets: '.target3',
        duration: 1000,
        ...
    }
])

Just Animate 2.0.0

August 8th, 2017

After months of work, Just Animate 2.0.0 is released! This version has many exciting features and a radically improved developer experience.

Greatly Improved Timeline

A lot of work went into improving the timeline to make it work with Web Animations API and with normal property interpolation alike.

Yo-yo and the Infinite Timeline

The timeline can now be set to play indefinitely and also alternate each time it repeats. The following code plays the animation forever and alternates between playing it forward and backward... like a yoyo!

var t1 = just.animate({
    targets: '.something-else',
    duration: 1000,
    ...
})

t1.play({ 
    repeat: Infinity, 
    alternate: true 
})

Timeline Gets Its Own Functions

To make it easier to build complex web choreography, timeline has its own function and has several new ways of adding events to the timeline. The following code adds three animation events to the timeline in a sequence:

var t1 = just.timeline()

t1.fromTo(0, 1000, {
    targets: '.first',
    ...
})

t1.add({
    duration: 1000,
    targets: '.second',
    ...
})

t1.add({
    from: 2000,
    to: 3000,
    targets: '.third',
    ...
})

t1.play()

The add() function adds the animation at the end of the timeline, but can be overriden using the to and from properties. There is also a fromTo() function to make it easy to have fine-grained control.

Props, Attributes, and CSS Variables Join The Fray

Props are Pretty Awesome!

Prior to version 2.0.0, the focus of Just Animate has been only on the Web Animations API. In this version, it is simple to also animate any numeric property on JavaScript objects or swap between discrete values. Using the props property, you can animate just about anything. The following code transitions between 0 and 100 on an object over 1000 milliseconds:

var myTarget = { x: 0 }

var t1 = just.animate({
    target: myTarget,
    duration: 1000,
    easing: 'linear',
    props: { x: 100 }
})

t1.play()

This feature makes it possible to choreograph position, rotation, and other properties of canvas libraries such as PixiJS and ThreeJS! By hooking into the update event on the timeline, you can even control the render cycles of those libraries. When the target is an HTMLElement, it will automatically assign props to attributes when applicable.

CSS Variables and Attributes

CSS Variables are a great way to make websites more reactive and animate new types of things. If the target is an HTMLElement and the property name starts with a double dash (--name), Just Animate will automatically get and set it as a CSS Variable. The following code animates a linear gradient as a progress bar (something that you can't currently do with the WAAPI alone):

.progress-bar {
    background: linear-gradient(
        to right,  
        #7AC7C4 calc(var(--progress) * 1%), 
        white calc(var(--progress) * 1%), 
        white
    )
}
var t1 = just.animate({
   targets: ".progress-bar",
   duration: 6000,
   props: {
     '--progress': [0, 100]
   }
})

Better WAAPI Integration

Web Changes For the Better

To improve integration with the Web Animation API and to remove weird edge cases, the fill, iteration, and direction properties have been removed from individual animations. The same effects can be achieved using the repeat, alternate, and the player functions. Additionally, all properties are now animated independently to allow for per property easings. To make room for additional property animations, WAAPI animations have been moved to the web property. For example, the following code fades in from the left:

var t1 = just.animate({
    targets: '.element',
    duration: 1000,
    web: {
        opacity: [0, 1],
        x: [-200, 0]
    }
})

Transform is Transformed

Transform shorthands are more flexible in Just Animate 2.0.0. Instead of relying on an implicity order, the order that transform properties appear on the timeline are the order that they are applied. To keep things simple, the transform property cannot be used in conjunction with x, y, z, scaleX, scaleY, scaleZ, scale, rotate, rotateX, rotateY, rotateZ, or perspective on the same target.

Easier Sequences

A top-level sequence helper has been added to make creating sequential animations even easier. Here is an example of how to use it:

var t1 = just.sequence([
    {
        targets: '.first',
        duration: 1000,
        ...
    },
    {
        targets: '.second',
        duration: 1000,
        ...
    },
    {
        targets: '.third',
        duration: 1000,
        ...
    }
])

The sequence() helper returns a timeline, so more animations can be added very easily.

Staggering Animations

To make staggering target animations easier, a stagger property has been added:

var t1 = just.animate({
    targets: '.list-item',
    stagger: 100,
    ...
})

This property moves each target resolved by targets down the timeline by its value. If for example, '.list-item' resolved three targets, the first animation would play at 100ms, the second at 200ms, and the third at 300ms.

Retired Features

Mixins/Presets Don't Make the Cut

The initial goal with 2.0.0 was to remove unused or heavy features. Presets accounted for one half of the library's size and and were not used extensively. They were removed to reduce the size of the library. This includes the mixin system and the easings outside of normal CSS keywords.

String Expressions are Quieted

The string expression for time was also removed. This feature allowed a developer or designer to say '100ms' or '.1s' instead of using a number of milliseconds for durations and times. While this seems like a handy feature, it made the API more complicated than necessary and combined with += notation, it added to the library's size. To keep things simple for everyone, this has been removed. There is no loss in functionality, all times are in milliseconds, and to do += things, a function can be used the same way as it could be used in 1.x:

var t1 = just.animate({
    targets: '.something',
    duration: 1000,
    delay: (target, index, targetLength) => index * 100,
    ...
})

t1.play()

Autoplay Gets Turned Off

This is a smaller change, but animations no longer autoplay. Removing this feature makes sense because it encourages developers and designers to build animations ahead of time and to be more selective about firing them. Animations now have an active and inactive phase. Calling .cancel() removes all effects and effectively resets the targets.