Flip动画的实现示例demo

发布于:2024-09-17 ⋅ 阅读:(132) ⋅ 点赞:(0)

文章说明

文章主要为了学习flip动画的实现思路,并且采用此示例效果来理解该实现思路的含义

参考渡一前端袁老师的讲解视频

核心代码

采用简单的y轴变化的动画效果为示例

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            margin: auto;
            margin-top: 100px;
            width: 100px;

            div {
                height: 30px;
                line-height: 30px;
                margin: 10px 0;
                background-color: chocolate;
                border-radius: 10px;
                color: #ffffff;
                text-align: center;
            }
        }
    </style>
</head>

<body>
    <div class="container">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>

    <button onclick="randomFlip()">点击flip</button>

    <script>
        function getElemConfig(container, children, first, last) {
            const elemFirst = container.children[first];
            const elemLast = container.children[last];
            const destElem = children[last];
            destElem.style.transform = `translateY(${elemLast.getBoundingClientRect().y - elemFirst.getBoundingClientRect().y}px)`;
            return destElem;
        }

        function play(destElem) {
            setTimeout(() => {
                for (let i = 0; i < destElem.length; i++) {
                    destElem[i].style.transition = "transform 1s";
                    destElem[i].style.removeProperty("transform");
                }
            }, 100);
        }

        function randomFlip() {
            const numbers = [];
            const container = document.getElementsByClassName("container")[0];
            const children = [];
            for (let i = 0; i < container.children.length; i++) {
                numbers.push(i);
                children.push(container.children[i].cloneNode(true));
            }
            const result = derange(numbers);
            const destElem = [];
            for (let i = 0; i < result.length; i++) {
                destElem.push(getElemConfig(container, children, i, result[i]));
            }

            container.innerHTML = "";
            for (let i = 0; i < destElem.length; i++) {
                container.appendChild(destElem[i]);
            }

            play(destElem);
        }

        function derange(array) {
            let derangedArray = array.slice();
            let i = derangedArray.length;
            while (i > 0) {
                let j = Math.floor(Math.random() * i);
                while (j === i || derangedArray[i] === derangedArray[j]) {
                    j = Math.floor(Math.random() * i);
                }
                [derangedArray[i - 1], derangedArray[j]] = [derangedArray[j], derangedArray[i - 1]];
                i--;
            }

            return derangedArray;
        }
    </script>
</body>

</html>

效果展示

在这里插入图片描述

采用translateY进行 transform 动画
在这里插入图片描述

Gif展示
在这里插入图片描述

Flip动画工具类的封装

在实现拖拽排序示例时,我在参考的学习视频中看到有关于Flip动画功能进行了封装,我于是自己研究了一下,封装了该工具,工具类如下

class Flip {
    children = null;
    delay = 0;

    constructor(children, delay = 1) {
        this.children = children;
        this.calculatePos();
        this.delay = delay;
    }

    calculatePos(name = "first") {
        const children = this.children;
        for (let i = 0; i < children.length; i++) {
            children[i][name] = children[i].getBoundingClientRect();
        }
    }

    play() {
        this.calculatePos("last");
        const children = this.children;
        for (let i = 0; i < children.length; i++) {
            const first = children[i]["first"];
            const last = children[i]["last"];
            if (first.x !== last.x || first.y !== last.y) {
                children[i].style.transform = `translateY(${first.y - last.y}px) translateX(${first.x - last.x}px)`;
                setTimeout(() => {
                    children[i].style.transition = `transform ${this.delay}s`;
                    children[i].style.removeProperty("transform");
                    setTimeout(() => {
                        children[i].style.removeProperty("transition");
                        this.calculatePos();
                    }, this.delay * 1000);
                }, 0);
            }
        }
    }
}

关于拖拽排序和该工具类的使用,可参考这篇文章–拖拽排序