<div class='animation-example'>
    <div class='set-1'>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
    </div>
    
    <div class='set-2'>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
        <div class='block'></div>
    </div>
    <div class='dots'>
        <div class='dot -active'></div>
        <div class='dot'></div>
        <div class='dot'></div>
        <div class='dot'></div>
        <div class='dot'></div>
    </div>
</div>
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

@size: 5vmin;

.animation-example {
    position: relative;
    height: 100vh;
    width: 100vw;
    overflow: hidden;
    
    > .set-1 {
        height: @size * 12;
        width: @size * 12;
        position: absolute;
        top: 50%;
        left: 0%;
        transform: translateX(20%) translateY(-50%) rotate(45deg) scale(1);
    }
    
    > .set-1 > .block {
        display: inline-block;
        position: relative;
        float: left;
        height: @size;
        width: @size;
        margin: @size;
        background: #EA638C;
    }
    
    > .set-2 {
        height: @size * 12;
        width: @size * 12;
        position: absolute;
        top: 50%;
        left: 150%;
        transform: translateX(-50%) translateY(-50%) rotate(0) scale(0);
    }
    
    > .set-2 > .block {
        display: inline-block;
        position: relative;
        float: left;
        height: @size;
        width: @size;
        margin: @size;
        background: #FFFFFF;
    }
    
    > .dots {
        position: absolute;
        bottom: 32px;
        left: 50%;
        transform: translateX(-50%);
        width: 100%;
        text-align: center;
    }
    
    > .dots > .dot {
        position: relative;
        display: inline-block;
        margin: 0 16px;
        height: 16px;
        width: 16px;
        border-radius: 50%;
        background: #000000;
    }
    
    > .dots > .dot::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 50%;
        height: 10px;
        width: 10px;
        border-radius: 50%;
        transform: translateX(-50%) translateY(-50%);
        background: #FFFFFF;
        opacity: 0;
        transition: opacity .5s ease-in-out;
        transition-delay: .3s;
    }
    
    > .dots > .dot.-active::after {
        opacity: 1;
    }
}
View Compiled
// 1. Get elements

const example = document.querySelector('.animation-example');
const set1    = example.querySelector('.set-1');
const set2    = example.querySelector('.set-2');
const blocks1 = set1.querySelectorAll('.block');
const blocks2 = set2.querySelectorAll('.block');
const dots    = example.querySelectorAll('.dot');


// 2. Set the states

const states = [
    // #1
    {
        randomRotateMod: 0,
        example: {
            background: 'rgb(255,255,255)'
        },
        set1: {
            top: '50%',
            left: '0%',
            translateX: '20%',
            translateY: '-50%',
            rotate: '45deg',
            scale: '1'
        },
        set2: {
            top: '50%',
            left: '150%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '0deg',
            scale: '0'
        },
        blocks1: {
            scale: '0.5'
        },
        blocks2: {
            scale: '1'
        }
    },
    
    // #2
    {
        randomRotateMod: 1,
        example: {
            background: 'rgb(255,255,255)'
        },
        set1: {
            top: '50%',
            left: '50%',
            translateX: '40%',
            translateY: '100%',
            rotate: '90deg',
            scale: '15'
        },
        set2: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '-90deg',
            scale: '0'
        },
        blocks1: {
            scale: '2.5'
        },
        blocks2: {
            scale: '0.1'
        }
    },
    
    // #3
    {
        randomRotateMod: 1,
        example: {
            background: 'rgb(255,255,255)'
        },
        set1: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '120deg',
            scale: '5.0'
        },
        set2: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '-45deg',
            scale: '5.5'
        },
        blocks1: {
            scale: '2.5'
        },
        blocks2: {
            scale: '0.1'
        }
    },
    
    // #4
    {
        randomRotateMod: 0,
        example: {
            background: 'rgb(234,99,140)'
        },
        set1: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '270deg',
            scale: '5.0'
        },
        set2: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '-180deg',
            scale: '1.7'
        },
        blocks1: {
            scale: '4'
        },
        blocks2: {
            scale: '1.02'
        }
    },
    
    // #5
    {
        randomRotateMod: 5,
        example: {
            background: 'rgb(255,255,255)'
        },
        set1: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '180deg',
            scale: '1.2'
        },
        set2: {
            top: '50%',
            left: '50%',
            translateX: '-50%',
            translateY: '-50%',
            rotate: '-180deg',
            scale: '2'
        },
        blocks1: {
            scale: '2.1'
        },
        blocks2: {
            scale: '0'
        }
    }
];


// 3. Init the first state

anime({
    targets: example,
    backgroundColor: states[0].example.background,
    duration: 0
});

anime({
    targets: set1,
    top: states[0].set1.top,
    left: states[0].set1.left,
    translateX: states[0].set1.translateX,
    translateY: states[0].set1.translateY,
    rotate: states[0].set1.rotate,
    scale: states[0].set1.scale,
    duration: 0
});


anime({
    targets: set2,
    top: states[0].set2.top,
    left: states[0].set2.left,
    translateX: states[0].set2.translateX,
    translateY: states[0].set2.translateY,
    rotate: states[0].set2.rotate,
    scale: states[0].set2.scale,
    duration: 0
});


for (block of blocks1) {
    anime({
        targets: block,
        scale: states[0].blocks1.scale,
        rotate: `${(Math.random() * 30 - 15) * states[0].randomRotateMod}deg`,
        duration: 0
    });
}

for (block of blocks2) {
    anime({
        targets: block,
        scale: states[0].blocks2.scale,
        rotate: `${(Math.random() * 30 - 15) * states[0].randomRotateMod}deg`,
        duration: 0
    });
}


// 4. Set interval or change the states manually

let currentStateIndex = 0;

setInterval(() => {
    const nextStateIndex = (currentStateIndex + 1) % states.length;

    anime({
        targets: example,
        backgroundColor: states[nextStateIndex].example.background,
        duration: 1000,
        easing: 'easeInOutQuint'
    });

    anime({
        targets: set1,
        top: states[nextStateIndex].set1.top,
        left: states[nextStateIndex].set1.left,
        translateX: states[nextStateIndex].set1.translateX,
        translateY: states[nextStateIndex].set1.translateY,
        rotate: states[nextStateIndex].set1.rotate,
        scale: states[nextStateIndex].set1.scale,
        duration: 1000,
        easing: 'easeInOutQuint'
    });
    
    anime({
        targets: set2,
        top: states[nextStateIndex].set2.top,
        left: states[nextStateIndex].set2.left,
        translateX: states[nextStateIndex].set2.translateX,
        translateY: states[nextStateIndex].set2.translateY,
        rotate: states[nextStateIndex].set2.rotate,
        scale: states[nextStateIndex].set2.scale,
        duration: 1000,
        easing: 'easeInOutQuint'
    });

    for (block of blocks1) {
        anime({
            targets: block,
            scale: states[nextStateIndex].blocks1.scale,
            rotate: `${(Math.random() * 30 - 15) * states[nextStateIndex].randomRotateMod}deg`,
            duration: 1000,
            easing: 'easeInOutQuint'
        });
    }
    
    for (block of blocks2) {
        anime({
            targets: block,
            scale: states[nextStateIndex].blocks2.scale,
            rotate: `${(Math.random() * 30 - 15) * states[nextStateIndex].randomRotateMod}deg`,
            duration: 1000,
            easing: 'easeInOutQuint'
        });
    }
    
    for (let i = 0; i < states.length; i++) {
        if (i <= nextStateIndex) {
            dots[i].classList.add('-active');
        } else {
            dots[i].classList.remove('-active');
        }
    }

    currentStateIndex = nextStateIndex;
}, 2000);

View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/animejs/3.1.0/anime.min.js