阅读 664

倒数动画效果

这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战

作者:battleKing
仓库:GithubCodePen
博客:CSDN掘金
反馈邮箱:myh19970701@foxmail.com
特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系笔者授权

背景

倒数动画 其实属于 加载动画 的一种,在用户心目中,优秀的应用、工具、网站都应该是制作精良且能快速响应他们需求的产品。以前我在发布一款产品的第一版时,登录验证的 loading... 延迟是 2-3秒,结果当天反馈邮箱就被用户挤爆了,大部分用户都认为这几秒是一个界面突然卡住是 软件BUG ,其实只是我们 验证登录信息 而已,所以如果没有 加载动画 告知用户我们在验证登录信息而只是让软件卡住不动的话,这是一种 非常不好的用户体验 ,虽然早期用户可能会给你的产品第二次机会,但绝大多数人对这款产品失去信息,不再使用,导致用户大量流失

解决方案:使用 加载动画,提供 即使反馈减少用户焦虑

加载动画分类进度条加载动画无限循环加载动画骨架图加载动画

优秀的加载动画特征

  1. 核心是 减少动画时间
  2. 给出 具体时间
  3. 告诉用户 为什么需要等待
  4. 让等待的过程不那么让人无聊 使用有趣的动画
  5. 减少用户等待时间的心理感知 色彩某个相关知识某条产品操作教学
  6. 透传公司品牌形象 公司理念公司价值观公司的标志吉祥物

最终效果

倒数动画.gif

一、添加 HTML 文件

<div class="counter">
    <div class="nums">
        <span class="in">3</span>
        <span>2</span>
        <span>1</span>
        <span>0</span>
    </div>
    <h4>Get Ready</h4>
</div>

<div class="final">
    <h1>GO</h1>
    <button id="replay">
        <span>Replay</span>
    </button>
</div>
复制代码

二、添加 CSS 文件

  1. 设置 *box-sizing: border-box
  2. 设置 body 来使整个项目居中
* {
* {
    box-sizing: border-box;
}

body {
    margin: 0;
    height: 100vh;
    overflow: hidden;
}
复制代码

主要的 CSS 代码

h4 {
    font-size: 20px;
    margin: 5px;
    text-transform: uppercase;
}

.counter {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
}

.counter.hide {
    transform: translate(-50%, -50%) scale(0);
    animation: hide 0.2s ease-out;
}

@keyframes hide {
    0% {
        transform: translate(-50%, -50%) scale(1);
    }

    100% {
        transform: translate(-50%, -50%) scale(0);
    }
}

.final {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scale(0);
    text-align: center;
}

.final.show {
    transform: translate(-50%, -50%) scale(1);
    animation: show 0.2s ease-out;
}

@keyframes show {
    0% {
        transform: translate(-50%, -50%) scale(0);
    }

    30% {
        transform: translate(-50%, -50%) scale(1.4);
    }

    100% {
        transform: translate(-50%, -50%) scale(1);
    }
}

.nums {
    color: #3498db;
    font-size: 50px;
    position: relative;
    overflow: hidden;
    width: 250px;
    height: 50px;
}

.nums span {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(120deg);
    transform-origin: bottom center;
}

.nums span.in {
    transform: translate(-50%, -50%) rotate(0deg);
    animation: goIn 0.5s ease-in-out;
}

.nums span.out {
    animation: goOut 0.5s ease-in-out;
}

@keyframes goIn {
    0% {
        transform: translate(-50%, -50%) rotate(120deg);
    }

    30% {
        transform: translate(-50%, -50%) rotate(-20deg);
    }

    60% {
        transform: translate(-50%, -50%) rotate(10deg);
    }

    100% {
        transform: translate(-50%, -50%) rotate(0deg);
    }
}

@keyframes goOut {
    0% {
        transform: translate(-50%, -50%) rotate(0deg);
    }

    60% {
        transform: translate(-50%, -50%) rotate(20deg);
    }

    100% {
        transform: translate(-50%, -50%) rotate(-120deg);
    }
}

#replay {
    background-color: #3498db;
    border-radius: 3px;
    border: none;
    color: aliceblue;
    padding: 5px;
    text-align: center;
    display: inline-block;
    cursor: pointer;
    transition: all 0.3s;
}

#replay span {
    cursor: pointer;
    display: inline-block;
    position: relative;
    transition: 0.3s;
}

#replay span:after {
    content: '\00bb';
    position: absolute;
    opacity: 0;
    top: 0;
    right: -20px;
    transition: 0.5s;
}

#replay:hover span {
    padding-right: 25px;
}

#replay:hover span:after {
    opacity: 1;
    right: 0;
}
复制代码

添加 JS 文件

主要逻辑

const nums = document.querySelectorAll('.nums span')
const counter = document.querySelector('.counter')
const finalMessage = document.querySelector('.final')
const replay = document.querySelector('#replay')

runAnimation()

function resetDOM() {
    counter.classList.remove('hide')
    finalMessage.classList.remove('show')

    nums.forEach((num) => {
        num.classList.value = ''
    })

    nums[0].classList.add('in')
}

function runAnimation() {
    nums.forEach((num, idx) => {
        const nextToLast = nums.length - 1

        num.addEventListener('animationend', (e) => {
            if (e.animationName === 'goIn' && idx !== nextToLast) {
                num.classList.remove('in')
                num.classList.add('out')
            } else if (e.animationName === 'goOut' && num.nextElementSibling) {
                num.nextElementSibling.classList.add('in')
            } else {
                counter.classList.add('hide')
                finalMessage.classList.add('show')
            }
        })
    })
}

replay.addEventListener('click', () => {
    resetDOM()
    runAnimation()
})
复制代码

❤️ 感谢大家

如果本文对你有帮助,就点个赞支持下吧,你的「赞」是我创作的动力。

如果你喜欢这篇文章的话,可以「点赞」 + 「收藏」 + 「转发」 给更多朋友。

文章分类
前端
文章标签