前端例程20220914:带悬停动画登陆页面

Posted Naisu Xu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端例程20220914:带悬停动画登陆页面相关的知识,希望对你有一定的参考价值。

演示

原理

对登陆框监听鼠标进入(mouseenter)和退出(mouseleave)事件。在鼠标进入时添加一个元素,并设置其扩大的动画;在鼠标退出时设置元素动画,并在动画完成后删除元素。

代码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <title>带悬停动画登陆页面</title>

    <style>
        * 
            padding: 0;
            margin: 0;
            user-select: none;
            box-sizing: border-box;
        

        html,
        body 
            height: 100vh;
        

        /* 全局色表 */
        :root 
            --color-bg: #304050;
            --color-bg-login: #34495D;
            --color-text: #eeeeee;
            --color-span: #907070;
        

        body 
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--color-bg);
        
    </style>

    <!-- 以下是登陆页面的基本样式 -->
    <style>
        .login 
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            width: 20rem;
            height: 28rem;
            background: var(--color-bg-login);
            border-radius: 1rem;
            box-shadow: 1rem 1rem 2rem rgba(0, 0, 0, 0.1);
        

        .login>h1 
            font-size: 3rem;
            font-weight: normal;
            color: var(--color-text);
            margin: 1rem;
            z-index: 1;
        

        .login>input 
            width: 12rem;
            height: 2rem;
            outline: none;
            background: transparent;
            border: none;
            border-bottom: 2px solid var(--color-text);
            color: var(--color-text);
            margin: 1rem;
            z-index: 1;
        

        .login>input::placeholder 
            color: rgba(255, 255, 255, 0.7);
        

        .login>button 
            width: 10rem;
            height: 2rem;
            background: transparent;
            outline: none;
            border-radius: 1rem;
            border: 2px solid var(--color-text);
            color: var(--color-text);
            margin: 1rem;
            cursor: pointer;
            z-index: 1;
        

        .login>button:active 
            backdrop-filter: invert(100%);
        
    </style>

    <!-- 以下是动画部分样式 -->
    <style>
        .login 
            position: relative;
            overflow: hidden;
        

        /* 下面使用span元素作为动画载体 */
        span 
            position: absolute;
            border-radius: 50%;
            background-color: var(--color-span);
            transform: translate(-50%, -50%);
        

        /* 鼠标进入login时的动画 */
        @keyframes mouseenter 
            0% 
                width: 0;
                height: 0;
            

            100% 
                width: 80rem;
                height: 80rem;
            
        

        /* 鼠标离开login时的动画 */
        @keyframes mouseleave 
            0% 
                width: 80rem;
                height: 80rem;
            

            100% 
                width: 0;
                height: 0;
            
        
    </style>
</head>

<body>
    <div class="login" id="login">
        <h1>Login</h1>
        <input type="text" placeholder="Username">
        <input type="text" placeholder="Password">
        <button>Log In</button>
    </div>

    <script>
        const login = document.querySelector("#login");
        let span;
        const animetime = 0.3; // 单边动画持续时间

        // 鼠标从外部进入登陆框时动画
        login.addEventListener("mouseenter", (e) => 
            if (span) 
                return;
            
            // 当前没有span元素则新建并赋值绑定
            span = document.createElement("span");
            span.style.top = `$e.offsetYpx`;
            span.style.left = `$e.offsetXpx`;
            span.style.animation = `mouseenter $animetimes ease-in forwards`;
            login.appendChild(span);
        );

        // 鼠标从登陆框退出时动画
        login.addEventListener("mouseleave", (e) => 
            if (!span) 
                return;
            
            // 当前有span元素才需要退出操作
            span.style.top = `$e.offsetYpx`;
            span.style.left = `$e.offsetXpx`;
            span.style.animation = `mouseleave $animetimes ease-out forwards`;
            // 动画结束后移除span元素
            setTimeout(() => 
                span.remove();
                span = undefined;
            , animetime * 1000);
        );
    </script>
</body>

</html>

补充说明

这个示例是参考自下面链接的的:
https://www.bilibili.com/video/BV1Bg411f7o5/
上面代码在一定情况下是会存在视觉上的问题的,主要存在当于鼠标快速滑动,在一个动画未完成就触发了另一个动画时就可以观察到相关现象。不过我觉得作为真实使用来说这种情况触发的概率一般,可以不管它。如果追求完美的话可以参考原视频。

当然原视频中的处理方案我觉得也一般,要更加完美的话可以使用 requestAnimationFrame 来处理。

更多例程

更多例程可以参考下面代码仓库:
https://github.com/NaisuXu/front-end-web-examples

以上是关于前端例程20220914:带悬停动画登陆页面的主要内容,如果未能解决你的问题,请参考以下文章

前端例程20220729:按钮悬停边框卷动效果

前端例程20221102:黑暗模式(Dark Mode)

前端例程20220913:粒子飘落效果动画背景

如何通过将鼠标悬停在同一页面上的图像上来触发 CSS 动画按钮

悬停时停止 CSS 动画

前端例程20220906:霓虹灯效按钮