前言
项目是基于Vue3+Element plus框架设计的,本来使用Element plus的Loading加载动效已经是满足项目需求的,但是感觉AntDesign的加载动效图标好看一点点,于是自行实现一个基于Vue3,以及仿AntDesign的加载动效的示例。其主要用到Vue3的createVNode和render函数。
一、示例代码
(1)/src/utils/antdLodingUtil/antdLoding.vue
<template>
<transition name="animation">
<div class="diy-loading-wrap" v-if="isOpen">
<div class="diy-loading-wrap-content">
<div class="diy-loading-wrap-content-spin">
<div class="ant-spin ant-spin-spinning">
<span class="ant-spin-dot ant-spin-dot-spin">
<i class="ant-spin-dot-item"></i>
<i class="ant-spin-dot-item"></i>
<i class="ant-spin-dot-item"></i>
<i class="ant-spin-dot-item"></i>
</span>
</div>
</div>
<p class="diy-loading-wrap-content-p">{
{
text }}</p>
</div>
</div>
</transition>
</template>
<script>
export default {
data() {
return {
isOpen: false,
text: '数据正在加载中...',
}
},
}
</script>
<style lang="less" scoped>
:root {
--el-mask-color: rgba(255, 255, 255, 0.9);
--el-transition-duration: 0.3s;
--el-transition-duration-fast: 0.2s;
--el-loading-spinner-size: 42px;
--el-loading-fullscreen-spinner-size: 50px;
}
/* animation 动画 */
.animation-enter-active{
animation: animationAction 0.3s;
}
.animation-leave-active{
animation: animationAction 0.5s reverse;
}
@keyframes animationAction {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* / animation 动画 */
.diy-loading-wrap {
position: absolute;
z-index: 2000;
background-color: var(--el-mask-color);
margin: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
transition: opacity var(--el-transition-duration);
}
.diy-loading-wrap .diy-loading-wrap-content {
top: 50%;
margin-top: calc((0px - var(--el-loading-spinner-size)) / 2);
width: 100%;
text-align: center;
position: absolute;
}
.diy-loading-wrap .diy-loading-wrap-content .diy-loading-wrap-content-spin {
.ant-spin {
box-sizing: border-box;
margin: 0;
padding: 0;
color: #000000d9;
font-size: 14px;
font-variant: tabular-nums;
line-height: 1.5715;
list-style: none;
font-feature-settings: tnum;
position: absolute;
display: none;
color: #1890ff;
text-align: center;
vertical-align: middle;
opacity: 0;
transition: transform .3s cubic-bezier(.78,.14,.15,.86)
}
.ant-spin-spinning {
position: static;
display: inline-block;
opacity: 1
}
.ant-spin-dot {
position: relative;
display: inline-block;
font-size: 20px;
width: 1em;
height: 1em
}
.ant-spin-dot-spin {
transform: rotate(45deg);
animation: antRotate 1.2s infinite linear
}
.ant-spin-dot-item {
position: absolute;
display: block;
width: 9px;
height: 9px;
background-color: #1890ff;
border-radius: 100%;
transform: scale(.75);
transform-origin: 50% 50%;
opacity: .3;
animation: antSpinMove 1s infinite linear alternate
}
.ant-spin-dot-item:nth-child(1) {
top: 0;
left: 0;
}
.ant-spin-dot-item:nth-child(2) {
top: 0;
right: 0;
animation-delay: .4s;
}
.ant-spin-dot-item:nth-child(3) {
right: 0;
bottom: 0;
animation-delay: .8s;
}
.ant-spin-dot-item:nth-child(4) {
bottom: 0;
left: 0;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
transform:rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
}
.diy-loading-wrap .diy-loading-wrap-content .diy-loading-wrap-content-p {
margin: 5px auto 0 auto;
color: #1890ff;
font-size: 14px;
}
</style>
(2)/src/utils/antdLodingUtil/antdLoding.js
import {
createVNode, render } from 'vue'
import loading from './antdLoding.vue'
let instance
/**
* 打开仿 Antd 加载的方法
* @param {*} option
*/
function showLoading(option) {
instance = createVNode(loading, option)
render(instance, document.querySelector('body'))
instance.component.data.isOpen = true
}
/**
* 关闭仿 Antd 加载的方法
*/
function hideLoading() {
if (instance) {
instance.component.data.isOpen = false
}
}
export {
showLoading,
hideLoading
}
(3)/src/views/Example/AntdLoding/index.vue
<template>
<div style="position: fixed; z-index: 9999; padding: 100px">
<el-button @click="handleOpenAntdLoding($event)" type="primary" size="small">open</el-button>
<el-button @click="handleCloseAntdLoding($event)" type="danger" size="small">close</el-button>
</div>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
/**
* 打开仿 Antd 加载的句柄方法
*/
handleOpenAntdLoding(evt) {
this.$elementUtil.handleElButtonBlur(evt)
this.$antdLodingUtil.showLoading({
author: '帅龍之龍' })
},
/**
* 关闭仿 Antd 加载的句柄方法
*/
handleCloseAntdLoding(evt) {
this.$elementUtil.handleElButtonBlur(evt)
this.$antdLodingUtil.hideLoading()
}
}
}
</script>
(4)/src/main.ts
// 引入仿Antd加载器工具并配置为全局方法
import * as antdLodingUtil from '@/utils/antdLodingUtil/antdLoding'
app.config.globalProperties.$antdLodingUtil = antdLodingUtil