【Anime.js】——Use Anime.js to achieve animation effects

Table of contents

Target:

​Edit 1, determine the idea

 2. Create a grid

 3. Set a random position

4. Create timeline animation

Full code:


Target:

Realize automatic point selection, first zoom out and then zoom in on the point, how to return to a state that is a little larger than other points, and zoom in from the outside to the inside with this point

1. Determine the train of thought

 2. Create a grid

Knowledge points:

createDocumentFragment() method:

It is used to create a virtual node object, or in other words, it is used to create a document fragment node. It can contain various types of nodes and is initially empty when created.

When you need to add multiple dom elements, if you add these elements to DocumentFragment first, and then add DocumentFragment to the page uniformly, the number of times the page renders dom will be reduced, and the efficiency will be significantly improved. 

 Effect:

 3. Set a random position

Knowledge points:

anime.stagger - stagger animation

anime.stagger(value, options)
//options 是一个对象类型:
    from: startingPosition  ————从哪里开始
    direction: '反向'  ————运动反向
    grid: [rows, columns]  ————网格


anime.stagger(value, {grid: [rows, columns], axis: 'x'})
//axis设置为x,表示将一整行设置为整体
//设为y,会将一整列设置为整体


//例如:
delay: anime.stagger(200, {grid: [14, 5], from: 'center'})

index : set a random starting point

Use the anime.set method to set the moving position for the little red dot cursor

 Effect:

4. Create timeline animation

(1) First realize the animation effect of the red dot

The frame animation is represented by keyframes, received by an array, and each frame is an object.

设置时间轴:
anime.timeline.add(parameters, offset);
//parameters 动画相关的参数————对象类型
//offset 时间偏移量————字符串或者数字类型
        // 字符串类型表示相对时间偏移,数字类型表示绝对偏移量

Effect:

(2) Realize the dynamic effect of white dots on the side

The targets target is a small white dot

 (3) The effect of fusing two points

These two points are not executed at the same time. To make them have an interlaced effect, set a delay for the second animation.

The second animation does not start until the end of the first animation, but starts after the execution of the entire time axis 30ms, and sets the time offset of the Number type.

 Effect:

(4) Create the third animation, let the red dot continue to translate down

 (5) Let the dot keep moving

The effect I see now is that it stops when it moves to the next point after moving to the next point. How can we keep it dynamic? That's right, we need loops.

Full code:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            background-color: #F6F4F2;
            color: #252423;
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            position: absolute;
            width: 100%;
            height: 100vh;
        }

        .animation-wrapper {
            width: 80%;
            padding-bottom: 40%;
        }

        .stagger-visualizer {
            position: absolute;
            width: 1100px;
            height: 550px;
            transform-origin: left top;
        }

        .stagger-visualizer .dots-wrapper {
            transform: translateZ(0);
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            align-items: center;
        }

        .stagger-visualizer .dot {
            position: relative;
            z-index: 1;
            width: 23px;
            height: 23px;
            margin: 16px;
            background-color: currentColor;
            border-radius: 50%;
        }

        @media (min-width: 740px) {
            .stagger-visualizer .dot {
                background-color: transparent;
                background-image: linear-gradient(180deg, #FFFFFF 8%, #D3CDC6 100%);
            }
        }

        .stagger-visualizer .cursor {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 37px;
            height: 37px;
            margin: 9px;
            background-color: currentColor;
            border-radius: 50%;
        }
    </style>
</head>

<body>
    <div class="animation-wrapper">
        <div class="stagger-visualizer">
            <div class="cursor color-red"></div>
            <div class="dots-wrapper"></div>
        </div>
    </div>
    <script src="../node_modules/animejs/lib//anime.min.js"></script>
    <script>
        function fitElementToParent(el, padding) {
            var timeout = null;
            function resize() {
                if (timeout) clearTimeout(timeout);
                anime.set(el, { scale: 1 });
                var pad = padding || 0;
                var parentEl = el.parentNode;
                var elOffsetWidth = el.offsetWidth - pad;
                var parentOffsetWidth = parentEl.offsetWidth;
                var ratio = parentOffsetWidth / elOffsetWidth;
                timeout = setTimeout(anime.set(el, { scale: ratio }), 10);
            }
            resize();
            window.addEventListener('resize', resize);
        }

        var advancedStaggeringAnimation = (function () {

            var staggerVisualizerEl = document.querySelector('.stagger-visualizer');
            var dotsWrapperEl = staggerVisualizerEl.querySelector('.dots-wrapper');
            var dotsFragment = document.createDocumentFragment();
            var grid = [20, 10];
            var cell = 55;
            var numberOfElements = grid[0] * grid[1];
            var animation;
            var paused = true;

            fitElementToParent(staggerVisualizerEl, 0);

            for (var i = 0; i < numberOfElements; i++) {
                var dotEl = document.createElement('div');
                dotEl.classList.add('dot');
                dotsFragment.appendChild(dotEl);
            }

            dotsWrapperEl.appendChild(dotsFragment);

            var index = anime.random(0, numberOfElements - 1);
            var nextIndex = 0;

            anime.set('.stagger-visualizer .cursor', {
                translateX: anime.stagger(-cell, { grid: grid, from: index, axis: 'x' }),
                translateY: anime.stagger(-cell, { grid: grid, from: index, axis: 'y' }),
                translateZ: 0,
                scale: 1.5,
            });

            function play() {

                paused = false;
                if (animation) animation.pause();

                nextIndex = anime.random(0, numberOfElements - 1);

                animation = anime.timeline({
                    easing: 'easeInOutQuad',
                    complete: play
                })
                    .add({
                        targets: '.stagger-visualizer .cursor',
                        keyframes: [
                            { scale: .75, duration: 120 },
                            { scale: 2.5, duration: 220 },
                            { scale: 1.5, duration: 450 },
                        ],
                        duration: 300
                    })
                    .add({
                        targets: '.stagger-visualizer .dot',
                        keyframes: [
                            {
                                translateX: anime.stagger('-2px', { grid: grid, from: index, axis: 'x' }),
                                translateY: anime.stagger('-2px', { grid: grid, from: index, axis: 'y' }),
                                duration: 100
                            }, {
                                translateX: anime.stagger('4px', { grid: grid, from: index, axis: 'x' }),
                                translateY: anime.stagger('4px', { grid: grid, from: index, axis: 'y' }),
                                scale: anime.stagger([2.6, 1], { grid: grid, from: index }),
                                duration: 225
                            }, {
                                translateX: 0,
                                translateY: 0,
                                scale: 1,
                                duration: 1200,
                            }
                        ],
                        delay: anime.stagger(80, { grid: grid, from: index })
                    }, 30)
                    .add({
                        targets: '.stagger-visualizer .cursor',
                        translateX: { value: anime.stagger(-cell, { grid: grid, from: nextIndex, axis: 'x' }) },
                        translateY: { value: anime.stagger(-cell, { grid: grid, from: nextIndex, axis: 'y' }) },
                        scale: 1.5,
                        easing: 'cubicBezier(.075, .2, .165, 1)'
                    }, '-=800')

                index = nextIndex;

            }

            play();

        })();
    </script>
</body>

</html>

Guess you like

Origin blog.csdn.net/qq_50497708/article/details/128347670