loading动效实现

在站上闲逛发现一个非常有意思的loading效果,跟着大佬仿写了一下Vue版本的。

https://blog.csdn.net/tianjian4592/article/details/44538605

在这里插入图片描述
直接放源码

<script setup>
import {ref, defineProps, watch} from "vue";

const props = defineProps({
    isShow: {
        type: Boolean,
        default: false
    },
    leafNum: {
        type: Number,
        default: 5
    }  // 叶子数量
})

const isLoading = ref(false);
const progressNum = ref(0);
let progress;
let leafIntervalArr;  // 保存leaf的定时器

watch(() => props.isShow, () => {
    if (!props.isShow) {
        // 触发关闭loading的时候延迟1.4s关闭,确保动画完整
        progressNum.value = 100;
        clearInterval(progress);
        setTimeout(() => {
            isLoading.value = false;
            progressNum.value = 0;
            // 结束动画后清空定时器
            for (let i = 0; i < leafIntervalArr.length; i++) {
                clearInterval(leafIntervalArr[i]);
            }
        }, 1400)
    } else {
        isLoading.value = true;
        setInterval(() => {
            if (progressNum.value <= 90) {
                progressNum.value += 1;
            }
        }, 300);
        setTimeout(() => {
            randomLeaf();
        }, 1000)
    }
})

function randomLeaf() {
    leafIntervalArr = new Array(props.leafNum);
    for (let i = 0; i < props.leafNum; i++) {
        let leaf = document.createElement('img');
        leaf.className = 'leaf';
        leaf.src = '/src/assets/images/loading/leaf.png';
        leaf.alt = '叶子';
        console.log(document.querySelector('.loading-progress'));
        document.querySelector('.loading-progress').appendChild(leaf);
        // 随机时间 1~5s
        setTimeout(() => {
            let activeLeaf = document.querySelectorAll('.leaf')[i];
            let x = 260, y = 0;
            activeLeaf.style.left = x + "px"; //初始坐标x
            activeLeaf.style.top = y + "px"; //初始坐标y

            leafIntervalArr[i] = setInterval(function () {
                x = x - 5; //运动速度
                y = Math.floor(Math.sin(x / 260 * 2 * Math.PI) * Math.floor(Math.random() * 10)) + Math.floor(Math.random() * 10); //运动的高度
                if (x < 0) x = 260;
                activeLeaf.style.left = x + "px";
                activeLeaf.style.top = y + "px";
                activeLeaf.style.transform = "rotate(" + Math.floor(Math.random() * 360) + "deg)";
            }, 100);
        }, Math.floor(Math.random() * 5000) + 1);
    }
}
</script>

<template>
    <transition>
        <div class="loading-container" v-if="isLoading">
            <div class="loading-text">loading...</div>
            <div class="loading-wrapper">
                <div class="loading-progress">
                    <div class="loading-progress-content" :style="{width: progressNum + '%'}"></div>
                    <!-- 叶子区域 -->
                </div>
                <div class="loading-fan fan-container">
                    <img class="fan" :class="{'fan-close':progressNum === 100}"
                         src="../../assets/images/loading/fan.png" alt="风扇">
                    <img class="max" v-if="progressNum === 100" src="../../assets/images/loading/100.png"
                         alt="100%">
                </div>
            </div>
        </div>
    </transition>
</template>

<style scoped>
.loading-container {
    width: 100vw;
    height: 100vh;
    background-color: #E3B12FD0;
    display: flex;
    justify-content: center;
    align-content: center;
    align-items: center;
    flex-wrap: wrap;
    position: fixed;
    top: 0;
    right: 0;
}

.loading-text {
    width: 100%;
    text-align: center;
    font-size: 20px;
    font-weight: bold;
    color: rgb(255, 168, 0);
    margin-bottom: 20px;
}

.loading-wrapper {
    width: 300px;
    height: 48px;
    background-color: #EED385D2;
    border-radius: 24px;
    position: relative;
    z-index: 9;
}

.loading-progress {
    width: 260px;
    height: 36px;
    background-color: #EED385D2;
    border-top-left-radius: 16px;
    border-bottom-left-radius: 16px;
    margin: 6px 0 6px 6px;
    overflow: hidden;
    position: absolute;
    top: 0;
    left: 0;
}

.loading-progress-content {
    width: 0;
    height: 36px;
    background-color: rgb(255, 168, 0);
    transition: all 0.5s;
    position: relative;
    z-index: 9;
}

.loading-fan {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background-color: rgb(251, 205, 81);
    border: 3px solid rgba(255, 255, 255, 0.6);
    box-sizing: border-box;
    position: absolute;
    top: 0;
    right: 0;
    z-index: 9;
}

.fan {
    width: 36px;
    height: 36px;
    position: absolute;
    top: 3px;
    left: 4px;
    animation: spin 2s infinite linear;
}

.fan-close {
    animation: fanClose 1.3s 1 linear;
    animation-fill-mode: forwards;
}

.max {
    width: 36px;
    height: 36px;
    position: absolute;
    top: 3px;
    left: 3px;
    animation: maxFont 1.3s 1 linear;
    animation-fill-mode: forwards;
}

@keyframes spin {
    from {
        transform: rotate(360deg);
    }
    to {
        transform: rotate(0deg);
    }
}

@keyframes fanClose {
    from {
        transform: rotate(360deg) scale(1);
    }
    to {
        transform: rotate(0deg) scale(0);
    }
}

@keyframes maxFont {
    from {
        transform: scale(0);
    }
    to {
        transform: scale(1);
    }
}
</style>
<style>
.leaf {
    width: 15px;
    height: 15px;
    position: absolute;
    top: 0;
    left: 260px;
    z-index: 5;
    transition: all 0.01s;
}
</style>

核心思想:

  1. css动画旋转风扇,根据时间慢慢增加进度条的宽度。
  2. 生成最大数量的叶子,随机事件、随机振幅、随机旋转角度从右向左沿正弦曲线运动
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前端开发中,实现 loading 可以通过 CSS 和 JavaScript 来完成,具体方式如下: 1. 使用 CSS 实现 loading 动画: 可以使用 CSS 的动画效果实现 loading 动画,例如使用 @keyframes 定义动画关键帧,然后使用 animation 属性将动画应用到指定元素上。示例代码如下: ```css @keyframes loading { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loading { width: 50px; height: 50px; border: 5px solid #ccc; border-top-color: #999; border-radius: 50%; animation: loading 1s linear infinite; } ``` 2. 使用 JavaScript 实现 loading 动画: 可以使用 JavaScript 动态创建 loading 元素,并设置其样式和动画,然后将 loading 元素添加到页面中。示例代码如下: ```javascript function showLoading() { // 创建 loading 元素 var loading = document.createElement('div'); loading.className = 'loading'; // 设置 loading 样式和动画 loading.style.width = '50px'; loading.style.height = '50px'; loading.style.border = '5px solid #ccc'; loading.style.borderTopColor = '#999'; loading.style.borderRadius = '50%'; loading.style.animation = 'loading 1s linear infinite'; // 将 loading 元素添加到页面中 document.body.appendChild(loading); } function hideLoading() { // 移除 loading 元素 var loading = document.querySelector('.loading'); if (loading) { loading.parentNode.removeChild(loading); } } ``` 以上代码实现了一个简单的 loading 动画,showLoading 函数用于显示 loading,hideLoading 函数用于隐藏 loading。可以根据实际需求调整 loading 的样式和动画。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值