1、前言
区域加载loading / 骨架屏,这一些用于用户等待数据的场景下的交互动作,是web性能优化的一个环节。下文主要讲解区域加载loading , 这里以element-ui组件的自定义指令v-loading ,自定义封装自定义指令(lottie 动画 / css样式)
2、element-ui的v-loading使用
这里不做过多的讲解,代码示例如下:
<MyButton
v-loading.fullscreen.lock="fullscreenLoading"
type="primary"
@click="openFullScreen1"
>
全屏指令
</MyButton>
<MyButton type="primary" @click="openFullScreen2">
全屏自定义指令
</MyButton>
// 全局loading
openFullScreen1 () {
this.fullscreenLoading = true
setTimeout(() => {
this.fullscreenLoading = false
}, 2000)
},
openFullScreen2 () {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
setTimeout(() => {
loading.close()
}, 2000)
},
3、自定义v-myLoading
- MyLoading.vue封装组件
<!--
* @Author: Null
* @Date: 2022-03-22 13:56:30
* @Description: MyLoading组件
-->
<template>
<div class="MyLoading" flex="main:center cross:center" v-on="$listeners">
<div v-if="customizedAttrs.loadingType === 'Fade-Circle'" class="loader-Fade-Circle" />
<div v-else-if="customizedAttrs.loadingType === '3D-Flip'" class="loader-3D-Flip" />
<div v-else-if="customizedAttrs.loadingType === 'Surround-Slice'" class="loader-Surround-Slice" />
<div v-else-if="customizedAttrs.loadingType === 'Surround-Circle'" class="loader-Surround-Circle" />
<!-- 默认加载loading -->
<div v-else-if="customizedAttrs.loadingType === 'default'" class="loader-default">
<div class="my-loading-loader">
<div class="my-loading" />
<div class="my-loading-text">加载中...</div>
</div>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'MyLoading',
inheritAttrs: false,
props: {
loadingType: {
type: String,
default: ''
}
},
computed: {
...mapState('element/myLoading', ['currentSelectedLoadingType']),
// Fade-Circle 渐隐圆环 ; 3D-Flip 翻转; Surround-Slice 环绕切片; Surround-Circle 环绕圆
customizedAttrs () {
if (this.loadingType) {
return {
loadingType: this.loadingType
}
} else {
return {
loadingType: this.currentSelectedLoadingType || 'default',
// 支持传过来的size覆盖默认的size
...this.$attrs
}
}
}
}
}
</script>
<style lang="scss">
.MyLoading {
position: relative;
width: 100%;
min-height: 100px;
border-radius: 3px;
font-size: 48px;
color: $color-primary;
padding: 1em;
margin-bottom: 0.15em;
vertical-align: top;
-webkit-transition: 0.3s color, 0.3s border;
transition: 0.3s color, 0.3s border;
}
[class*='loader-'] {
display: inline-block;
width: 1em;
height: 1em;
color: inherit;
vertical-align: middle;
pointer-events: none;
}
.loader-Fade-Circle {
position: relative;
}
.loader-Fade-Circle:before,
.loader-Fade-Circle:after {
content: '';
width: inherit;
height: inherit;
border-radius: 50%;
background-color: currentcolor;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
-webkit-animation: loader-Fade-Circle 2s infinite ease-in-out;
animation: loader-Fade-Circle 2s infinite ease-in-out;
}
.loader-Fade-Circle:after {
-webkit-animation-delay: -1s;
animation-delay: -1s;
}
@-webkit-keyframes loader-Fade-Circle {
0%,
100% {
-webkit-transform: scale(0);
transform: scale(0);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
@keyframes loader-Fade-Circle {
0%,
100% {
-webkit-transform: scale(0);
transform: scale(0);
}
50% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
.loader-3D-Flip {
background-color: currentcolor;
border-radius: 8px;
background: url('../../assets/images/logo.png') center no-repeat;
background-size: 100% 100%;
-webkit-animation: loader-3D-Flip 1.2s infinite ease-in-out;
animation: loader-3D-Flip 1.2s infinite ease-in-out;
}
@-webkit-keyframes loader-3D-Flip {
0% {
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
}
50% {
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
}
100% {
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
@keyframes loader-3D-Flip {
0% {
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg);
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
}
50% {
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
}
100% {
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
.loader-Surround-Slice {
-webkit-transform: rotateZ(45deg);
transform: rotateZ(45deg);
-webkit-perspective: 1000px;
perspective: 1000px;
border-radius: 50%;
}
.loader-Surround-Slice:before,
.loader-Surround-Slice:after {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: inherit;
height: inherit;
border-radius: 50%;
-webkit-animation: 1s spin linear infinite;
animation: 1s spin linear infinite;
}
.loader-Surround-Slice:before {
-webkit-transform: rotateX(70deg);
transform: rotateX(70deg);
}
.loader-Surround-Slice:after {
-webkit-transform: rotateY(70deg);
transform: rotateY(70deg);
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
@-webkit-keyframes spin {
0%,
100% {
box-shadow: 0.2em 0px 0 0px currentcolor;
}
12% {
box-shadow: 0.2em 0.2em 0 0 currentcolor;
}
25% {
box-shadow: 0 0.2em 0 0px currentcolor;
}
37% {
box-shadow: -0.2em 0.2em 0 0 currentcolor;
}
50% {
box-shadow: -0.2em 0 0 0 currentcolor;
}
62% {
box-shadow: -0.2em -0.2em 0 0 currentcolor;
}
75% {
box-shadow: 0px -0.2em 0 0 currentcolor;
}
87% {
box-shadow: 0.2em -0.2em 0 0 currentcolor;
}
}
@keyframes spin {
0%,
100% {
box-shadow: 0.2em 0px 0 0px currentcolor;
}
12% {
box-shadow: 0.2em 0.2em 0 0 currentcolor;
}
25% {
box-shadow: 0 0.2em 0 0px currentcolor;
}
37% {
box-shadow: -0.2em 0.2em 0 0 currentcolor;
}
50% {
box-shadow: -0.2em 0 0 0 currentcolor;
}
62% {
box-shadow: -0.2em -0.2em 0 0 currentcolor;
}
75% {
box-shadow: 0px -0.2em 0 0 currentcolor;
}
87% {
box-shadow: 0.2em -0.2em 0 0 currentcolor;
}
}
.loader-Surround-Circle {
position: relative;
background-color: currentcolor;
border-radius: 50%;
}
.loader-Surround-Circle:after,
.loader-Surround-Circle:before {
content: '';
position: absolute;
width: 0.25em;
height: 0.25em;
border-radius: 50%;
opacity: 0.8;
}
.loader-Surround-Circle:after {
left: -0.5em;
top: -0.25em;
background-color: currentcolor;
-webkit-transform-origin: 0.75em 1em;
transform-origin: 0.75em 1em;
-webkit-animation: loader-Surround-Circle 1s linear infinite;
animation: loader-Surround-Circle 1s linear infinite;
opacity: 0.6;
}
.loader-Surround-Circle:before {
left: -1.25em;
top: -0.75em;
background-color: currentcolor;
-webkit-transform-origin: 1.5em 1em;
transform-origin: 1.5em 1em;
-webkit-animation: loader-Surround-Circle 2s linear infinite;
animation: loader-Surround-Circle 2s linear infinite;
}
@-webkit-keyframes loader-Surround-Circle {
0% {
-webkit-transform: rotateZ(0deg) translate3d(0, 0, 0);
transform: rotateZ(0deg) translate3d(0, 0, 0);
}
100% {
-webkit-transform: rotateZ(360deg) translate3d(0, 0, 0);
transform: rotateZ(360deg) translate3d(0, 0, 0);
}
}
@keyframes loader-Surround-Circle {
0% {
-webkit-transform: rotateZ(0deg) translate3d(0, 0, 0);
transform: rotateZ(0deg) translate3d(0, 0, 0);
}
100% {
-webkit-transform: rotateZ(360deg) translate3d(0, 0, 0);
transform: rotateZ(360deg) translate3d(0, 0, 0);
}
}
/* 默认加载动画 */
.my-loading-loader {
position: relative;
font-size: 12px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 60px;
}
.my-loading-loader .my-loading {
position: relative;
width: 100%;
height: 10px;
border: 1px solid $color-primary;
border-radius: 10px;
animation: turnDefault 1s linear 0.42s infinite;
}
.my-loading-loader .my-loading:before {
content: "";
display: block;
position: absolute;
width: 0%;
height: 100%;
background: $color-primary;
box-shadow: 10px 0px 15px 0px $color-primary;
animation: loadDefault .5s linear infinite;
}
.my-loading-loader .my-loading-text {
width: 100%;
position: absolute;
top: 10px;
color: $color-primary;
text-align: center;
animation: bounceDefault .5s linear infinite;
}
@keyframes loadDefault {
0% {
width: 0%;
}
87.5%,
100% {
width: 100%;
}
}
@keyframes turnDefault {
0% {
transform: rotateY(0deg);
}
6.25%,
50% {
transform: rotateY(180deg);
}
56.25%,
100% {
transform: rotateY(360deg);
}
}
@keyframes bounceDefault {
0%,
100% {
top: 10px;
}
12.5% {
top: 30px;
}
}
/* 默认加载动画 */
</style>
- 页面中使用
<div class="MyLoading-display">
<MyLoading />
<MyLoading loading-type="3D-Flip" />
<MyLoading loading-type="Surround-Slice" />
<MyLoading loading-type="Surround-Circle" />
<MyLoading loading-type="default" />
</div>
3、自定义v-myLoading
- CSS的loading
- vue-lottie安装
npm install vue-lottie
yarn add vue-lottie
"vue-lottie": "^0.2.1",
- MyLottie组件封装
【注意,这里的lottie的动画模型,需要在lottie官网中去下载,也可以去我的源码内拿取】
MyLottie/index.vue 文件
<!--
* @Author: Null
* @Date: 2022-03-28 17:45:27
* @Description: lottie动画
-->
<template>
<div class="MyLottie" flex="main:center cross:center">
<VueLottie v-bind="VueLottieOptions" @animCreated="handleAnimation" />
</div>
</template>
<script>
import Loading0 from './lottieModel/loading0.json'
import Loading1 from './lottieModel/loading1.json'
import Loading2 from './lottieModel/loading2.json'
import Loading3 from './lottieModel/loading3.json'
import Loading4 from './lottieModel/loading4.json'
export default {
name: 'MyLottie',
props: {
lottieType: {
type: String,
default: 'loading0'
}
},
data () {
return {
anim1: {},
VueLottieOptions: {
height: 140,
width: 140,
options: {
animationData: Loading0
}
}
}
},
created () {
this.judgeLottieType(this.lottieType)
},
methods: {
handleAnimation (anim) {
this.anim1 = anim
},
// 判断动画json文件
judgeLottieType (type) {
let loadingType = Loading0
if (type === 'loading0') {
loadingType = Loading0
} else if (type === 'loading1') {
loadingType = Loading1
} else if (type === 'loading2') {
loadingType = Loading2
} else if (type === 'loading3') {
loadingType = Loading3
} else if (type === 'loading4') {
loadingType = Loading4
}
this.VueLottieOptions.options.animationData = loadingType
}
}
}
</script>
<style lang="scss" scoped>
.MyLottie {
width: 100%;
height: 100%;
}
</style>
MyLottie/lottieModel/loading1.json 文件
{"v":"4.10.1","fr":24,"ip":0,"op":72,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Capa de formas 12","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":24,"s":[81.5,370.25,0],"e":[445.5,199.25,0],"to":[60.6666679382324,-28.5,0],"ti":[-60.6666679382324,28.5,0]},{"t":48}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[43,43,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[28,0],[34.935,-19.483],[31.619,18.821],[33,-14],[57,29],[0,0],[0,0],[0,0]],"o":[[-28,0],[-52,29],[-42,-25],[-28.892,12.257],[-57,-29],[0,0],[0,0],[0,0]],"v":[[367.75,-97],[277,-75],[155,-82],[35,-82],[-94,-82.326],[-200,-74],[-352.07,320.209],[499.162,354.093]],"c":true},"ix":2},"nm":"Trazado 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2980392156862745,0.7333333333333333,0.6313725490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Forma 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":144,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Capa de formas 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":24,"s":[-133,374,0],"e":[231,203,0],"to":[60.6666679382324,-28.5,0],"ti":[-60.6666679382324,28.5,0]},{"t":48}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[43,43,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[28,0],[34.935,-19.483],[31.619,18.821],[33,-14],[57,29],[0,0],[0,0],[0,0]],"o":[[-28,0],[-52,29],[-42,-25],[-28.892,12.257],[-57,-29],[0,0],[0,0],[0,0]],"v":[[367.75,-97],[277,-75],[155,-82],[35,-82],[-94,-82.326],[-200,-74],[-352.07,320.209],[499.162,354.093]],"c":true},"ix":2},"nm":"Trazado 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.3137254901960784,0.8901960784313725,0.7607843137254902,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Forma 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":144,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Capa de formas 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":15,"s":[100],"e":[0]},{"t":16}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[199,-14.000000000000002,0],"e":[199,156,0],"to":[0,28.3333339691162,0],"ti":[0,-28.9375,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":12,"s":[199,156,0],"e":[199,164.066,0],"to":[0,4.54861259460449,0],"ti":[0,-2.45892143249512,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":13,"s":[199,164.066,0],"e":[199,166.125,0],"to":[0,13.1843204498291,0],"ti":[0,-1.72074222564697,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":14,"s":[199,166.125,0],"e":[199,168.375,0],"to":[0,2.04166674613953,0],"ti":[0,-0.04166666790843,0]},{"t":15}],"ix":2},"a":{"a":0,"k":[-1,-182.375,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[50,50,100],"e":[50,94,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":12,"s":[50,94,100],"e":[70,43.333,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":13,"s":[70,43.333,100],"e":[104.25800000000001,32,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":14,"s":[104.25800000000001,32,100],"e":[212,18,100]},{"t":15}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.938,0],[0,-5.25],[-4.563,0.125],[0.108,4.624]],"o":[[-0.813,0.125],[0,4.813],[4.563,-0.125],[-0.125,-5.375]],"v":[[-1.344,-193.078],[-8.75,-180.5],[-1.063,-172.313],[6.938,-180.188]],"c":true},"ix":2},"nm":"Trazado 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2980392156862745,0.7333333333333333,0.6313725490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Forma 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Capa de formas 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":46,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":47,"s":[100],"e":[100]},{"t":48}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":47,"s":[199.98,168.25,0],"e":[199.98,158.037,0],"to":[0,-0.20375619828701,0],"ti":[0,17.58864402771,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":48,"s":[199.98,158.037,0],"e":[199.98,-10,0],"to":[-2.8421709430404e-14,-50.4047393798828,0],"ti":[0,1.17485654354095,0]},{"t":53}],"ix":2},"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":47,"s":[-4,1,100],"e":[1.5,4,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":48,"s":[1.5,4,100],"e":[2,3,100]},{"t":53}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[308,308],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Trazado elíptico 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2980392156862745,0.7333333333333333,0.6313725490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Capa de formas 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[199,252.99999999999997,0],"ix":2},"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":0,"k":[55.00000000000001,55.00000000000001,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[308,308],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Trazado elíptico 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.2980392156862745,0.7333333333333333,0.6313725490196078,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":12,"s":[50],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":24,"s":[100],"e":[50]},{"t":48}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":12,"s":[50],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":24,"s":[0],"e":[50]},{"t":48}],"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Recortar trazados 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Capa de formas 1","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[199,252.99999999999997,0],"ix":2},"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":0,"k":[50,50,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[308,308],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Trazado elíptico 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2980392156862745,0.7333333333333333,0.6313725490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"Precomp. 1","tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2},"a":{"a":0,"k":[200,200,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":400,"h":400,"ip":0,"op":144,"st":0,"bm":0}]}
- 封装为全局指令
directives/myLoading/index.js
import Vue from 'vue'
import Loading from './MyLoading.vue'
/**
* Vue.extend 接受参数并返回一个构造器,new 该构造器可以返回一个组件实例
* 当我们 new Mask() 的时候,把该组件实例挂载到一个 div 上
**/
const Mask = Vue.extend(Loading)
// myLoadingType: 'default'
// 更新是否显示
const toggleLoading = (el, binding) => {
if (binding.value) {
Vue.nextTick(() => {
// 控制loading组件显示
el.instance.visible = true
el.style.position = 'relative'
// 插入到目标元素
insertDom(el, el)
})
} else {
el.instance.visible = false
el.style.position = 'static'
el.mask && el.mask.parentNode && el.mask.parentNode.removeChild(el.mask)
}
}
// 插入到目标元素
const insertDom = (parent, el) => {
parent.appendChild(el.mask)
}
export default {
// 第一次绑定到元素时调用
bind: function (el, binding, vnode) {
const { modifiers } = binding
let myLoadingType = 'default'
if (modifiers) {
const arr = Object.keys(modifiers)
if (arr.length) {
console.log('获取自定义指令myLoading修饰符 ======>', modifiers)
myLoadingType = ['lottie', 'lottie1', 'lottie2', 'lottie3', 'lottie4'].includes(arr[0]) ? arr[0] : 'default'
}
}
const mask = new Mask({
el: document.createElement('div'),
data () {
return {
myLoadingType: myLoadingType
}
}
})
// console.log('mask====>', mask)
// 用一个变量接住mask实例
el.instance = mask
el.mask = mask.$el
el.maskStyle = {}
binding.value && toggleLoading(el, binding)
},
// 所在组件的 VNode 更新时调用--比较更新前后的值
update: function (el, binding) {
if (binding.oldValue !== binding.value) {
toggleLoading(el, binding)
}
},
// 指令与元素解绑时调用
unbind: function (el, binding) {
el.instance && el.instance.$destroy()
}
}
directives/myLoading/MyLoading.vue
<template>
<div class="myLoading-container borderRed">
<!-- 默认加载loading -->
<div v-if="myLoadingType === 'default'" class="loader">
<div class="my-loading" />
<div class="my-loading-text">加载中...</div>
</div>
<!-- <MyLoading v-if="myLoadingType === 'default'" /> -->
<!-- MyLottie 动画loading -->
<MyLottie v-else-if="myLoadingType === 'lottie'" />
<MyLottie v-else-if="myLoadingType === 'lottie0'" lottie-type="loading0" />
<MyLottie v-else-if="myLoadingType === 'lottie1'" lottie-type="loading1" />
<MyLottie v-else-if="myLoadingType === 'lottie2'" lottie-type="loading2" />
<MyLottie v-else-if="myLoadingType === 'lottie3'" lottie-type="loading3" />
<MyLottie v-else-if="myLoadingType === 'lottie4'" lottie-type="loading4" />
</div>
</template>
<script>
export default {
name: 'MyLoading'
}
</script>
<style lang ="scss" scoped>
.myLoading-container {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
min-height: 60px;
background-color: rgba(255, 255, 255, 0.8);
}
/* 默认加载动画 */
.loader {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 60px;
}
.loader .my-loading {
position: relative;
width: 100%;
height: 10px;
border: 1px solid $color-primary;
border-radius: 10px;
animation: turn 1s linear 0.42s infinite;
}
.loader .my-loading:before {
content: "";
display: block;
position: absolute;
width: 0%;
height: 100%;
background: $color-primary;
box-shadow: 10px 0px 15px 0px $color-primary;
animation: load .5s linear infinite;
}
.loader .my-loading-text {
width: 100%;
position: absolute;
top: 10px;
color: $color-primary;
text-align: center;
animation: bounce .5s linear infinite;
}
@keyframes load {
0% {
width: 0%;
}
87.5%,
100% {
width: 100%;
}
}
@keyframes turn {
0% {
transform: rotateY(0deg);
}
6.25%,
50% {
transform: rotateY(180deg);
}
56.25%,
100% {
transform: rotateY(360deg);
}
}
@keyframes bounce {
0%,
100% {
top: 10px;
}
12.5% {
top: 30px;
}
}
/* 默认加载动画 */
</style>
- 注册指令
import myLoading from './myLoading'
export default {
install (Vue) {
// 自定义loading指令
Vue.directive('myLoading', myLoading)
}
}
- 页面使用
<div slot="content" flex>
<div
v-myLoading="true"
class="dk-container-h350w350 dk-mr-10 borderRed"
flex="main:center cross:center"
>
测试
</div>
<div
v-myLoading.lottie="true"
class="dk-container-h350w350 dk-mr-10 borderRed"
flex="main:center cross:center"
>
测试
</div>
<div
v-myLoading.lottie1="true"
class="dk-container-h350w350 dk-mr-10 borderRed"
flex="main:center cross:center"
>
测试
</div>
<div
v-myLoading.lottie2="true"
class="dk-container-h350w350 dk-mr-10 borderRed"
flex="main:center cross:center"
>
测试
</div>
<div
v-myLoading.lottie3="true"
class="dk-container-h350w350 dk-mr-10 borderRed"
flex="main:center cross:center"
>
测试
</div>
</div>
【补充】:如果有什么看不懂的,可以将上方的源码下载下来,copy代码
完结散花...