A Guide to Animations with Vue.js

Vue.js is a framework with high potential. It’s easy to learn, fast, and light in terms of bytes. Now, I’m going to continue my journey through this framework with a more relaxing piece about Vue.js animations. We’ll implement some basic sorting algorithms and animate each sort move.

You’ll find the final result in my repository.

First Steps

First of all, let’s create four new files:

  • index.html
  • app.js
  • style.css
  • sorting.js

Add the reference to the style sheet to index.html, to our two JavaScripts file, and, of course, to Vue.js:

 <head>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <link href="style.css" rel="stylesheet" />
  </head>

  <!-- ... -->

  <script src="sorting.js"></script>
  <script src="app.js"></script>

</body>

Then make a draft of our application appearance:

A draft look of our animation playground with Vue.js

As you can see, our application is composed of:

  • A set of balls, where even numbers are red and odd numbers are black
  • “Shuffle!” button: to make the array not unordered
  • “Bubble sort” button: to sort the array with bubble sort
  • “Selection sort” button: to sort the array with bubble sort
  • “Insertion sort” button: to sort the array with bubble sort

Sorting Algorithms

We need to implement a function for each button. A little trick to slow down each sorting operation is to define a sleep function in order to let the animation play in a visible time, otherwise it will be too fast to see the moves.

We’ll put each of these functions in the sorting.js file.

function sleep() {
    return new Promise(resolve => setTimeout(resolve, 550));
}

The sleep function that’ll wait 550 milliseconds

Then, we’ll need two methods to let Vue.js notify that the array is changed. The solution is to not use the [x] operator to swap items but use splice(). Remember that the Vue.js array notifies changes only when these methods are called:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
function arraySetWithoutIndexes(array, index, value) {
    array.splice(index, 1, value);
}

function arraySwap(array, indexA, indexB) {
    var x = array[indexA];
    arraySetWithoutIndexes(array, indexA, array[indexB]);
    arraySetWithoutIndexes(array, indexB, x);
}

Let’s define a shuffle function to mess with the array elements’ positions:

async function shuffle(a) {

    var j, i;
    for (i = a.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        arraySwap(a, i, j);
        await sleep();
    }

}

Notice the use of:

  • async: we want to asynchronously wait for the sleep operation to complete
  • arraySwap: swapping elements with splice() in order to notify the swap to our representation of the array
  • sleep: in order to slow down each swap operation

Bubble sort:

async function bubbleSort(a) {

    var len = a.length;
    for (var i = len - 1; i >= 0; i--) {
        for (var j = 1; j <= i; j++) {
            if (a[j - 1] > a[j]) {
                arraySwap(a, j - 1, j);
                await sleep();
            }
        }
    }

}

Selection sort:

async function selectionSort(a) {

    var minIdx, temp,
        len = a.length;

    for (var i = 0; i < len; i++) {
        minIdx = i;
        for (var j = i + 1; j < len; j++) {
            if (a[j] < a[minIdx]) {
                minIdx = j;
            }
        }

        arraySwap(a, i, minIdx);
        await sleep();
    }

}

Insertion sort:

async function insertionSort(a) {

    var i, len = a.length, el, j;

    for (i = 1; i < len; i++) {
        el = a[i];
        j = i;

        while (j > 0 && a[j - 1] > el) {
            a[j] = a[j - 1];
            j--;
        }

        arraySetWithoutIndexes(a, j, el);
        await sleep();
    }

}

The HTML Template

<div id="app-sorting">

	<div>
		<transition name="fade" v-if="!isManipulatingArray">
			<div class="buttons-container">
				<button class="button" v-on:click="shuffle()"><span>{{ shuffleButtonText }}</span></button>
				<button class="button" v-for="b in sortAlgorithms" v-on:click="sort(b)">{{ b.name }}</button>
			</div>
		</transition>
	</div>

	<transition-group tag="div" name="list-animation" class="array-to-be-sorted">
		<div v-for="num in arrayToBeSorted" v-bind:key="num" v-bind:class="[ num % 2 == 0 ? 'even' : 'odd', 'list-animation-item', 'list-item' ]">
			<span>{{ num }}</span>
		</div>
	</transition-group>

</div>

As you can see, our template is divided into two parts:

  • The buttons container that’ll hold the interaction buttons and hide it when the array is being manipulated in order to avoid the user mess with the current running algorithm
  • The array representation with a transition-group in order to render the animation. The array is represented only with a simple v-for.

The Vue.js application

In our app.js, we’ll define this Vue.js application:

var sortingApp = new Vue({

    el: '#app-sorting',

    data: {

        arrayToBeSorted: [1, 2, 3, 4, 5, 6, 7, 8],
        isManipulatingArray: false,

        shuffleButtonText: "Shuffle!",

        sortAlgorithms: [
            { name: "Bubble sort", fn: bubbleSort },
            { name: "Selection sort", fn: selectionSort },
            { name: "Insertion sort", fn: insertionSort }
        ]

    },

    methods: {

        shuffle: function () {
            this.isManipulatingArray = true;
            shuffle(this.arrayToBeSorted).then(() => this.isManipulatingArray = false);
        },

        sort: function (sortAlgorithm) {
            this.isManipulatingArray = true;
            sortAlgorithm.fn(this.arrayToBeSorted).then(() => this.isManipulatingArray = false);
        }

    }

});

As you can see, the list of sorting functions are defined in an array with a name and a function delegate, in order to make them bind with the buttons container.

Moreover, the shuffle and sort functions manage the isManipulatingArray property to notify the template when to show or hide the buttons container.

The Animations

Animations are written in the CSS file. They’re quite basic, we’ll just:

  • The fade animation of the buttons container div are obtained with the opacity and transform properties
  • All array element moves come free with the transition-all-properties-with-ease function
.list-animation-item {
    transition: all ease 0.5s;
}

.fade-enter-active, .fade-leave-active {
    transition: all ease 1s;
}

.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
    opacity: 0;
    transform: translateY(-30px) scale(0.9);
}

The Final Result

This is image title

Thank you for reading! If you enjoyed this article, please share it with others who may enjoy it as well.!

#Vuejs #Vue #JavaScript #Programming #Web Development

A Guide to Animations with Vue.js
1 Likes37.55 GEEK