个人博客网站欢迎交流:萤火之森:https://blog.xkongkeji.com
组件API:TigerUi:http://tigerui.xkongkeji.com
效果图
结构
<template>
<div :class="['ti-loading', 'ti-' + type]">
<div class="loader-inner">
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<div class="loader-line-wrap">
<div class="loader-line"></div>
</div>
<span v-if="text" class="loading-text">{{ text }}</span>
</div>
</div>
</template>
<script>
export default {
name: "TiLoading",
props: ["text", "type"],
};
</script>
<style lang="scss" scoped>
.ti-service {
position: fixed;
bottom: 0;
left: 0;
right: 0;
top: 0;
z-index: 99999;
}
.ti-directive {
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
z-index: 99999;
}
.ti-loading {
background: #000;
background: radial-gradient(#222, #000);
opacity: 0.5;
overflow: hidden;
}
.loader-inner {
bottom: 0;
height: 60px;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 100px;
}
.loading-text {
position: absolute;
left: 50%;
bottom: -70px;
width: 200px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
transform: translateX(-50%);
color: #409eff;
}
.loader-line-wrap {
animation: spin 2000ms cubic-bezier(0.175, 0.885, 0.32, 1.275) infinite;
box-sizing: border-box;
height: 50px;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
transform-origin: 50% 100%;
width: 100px;
}
.loader-line {
border: 4px solid transparent;
border-radius: 100%;
box-sizing: border-box;
height: 100px;
left: 0;
margin: 0 auto;
position: absolute;
right: 0;
top: 0;
width: 100px;
}
.loader-line-wrap:nth-child(1) {
animation-delay: -50ms;
}
.loader-line-wrap:nth-child(2) {
animation-delay: -100ms;
}
.loader-line-wrap:nth-child(3) {
animation-delay: -150ms;
}
.loader-line-wrap:nth-child(4) {
animation-delay: -200ms;
}
.loader-line-wrap:nth-child(5) {
animation-delay: -250ms;
}
.loader-line-wrap:nth-child(1) .loader-line {
border-color: hsl(0, 80%, 60%);
height: 90px;
width: 90px;
top: 7px;
}
.loader-line-wrap:nth-child(2) .loader-line {
border-color: hsl(60, 80%, 60%);
height: 76px;
width: 76px;
top: 14px;
}
.loader-line-wrap:nth-child(3) .loader-line {
border-color: hsl(120, 80%, 60%);
height: 62px;
width: 62px;
top: 21px;
}
.loader-line-wrap:nth-child(4) .loader-line {
border-color: hsl(180, 80%, 60%);
height: 48px;
width: 48px;
top: 28px;
}
.loader-line-wrap:nth-child(5) .loader-line {
border-color: hsl(240, 80%, 60%);
height: 34px;
width: 34px;
top: 35px;
}
@keyframes spin {
0%,
15% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
</style>
服务开启模式
import Vue from "vue";
import loadingBase from "./main.vue";
const loadingConstructor = Vue.extend(loadingBase);
/**
* @Function open 打开loading
* @Function close 关闭lading
*/
class serviceLoading {
constructor() {
this._instance_ = null;
this._parent_ = null;
this._loadingList_ = [];
this.overflow = false; // 判断滚动条是否处于禁用状态
}
/**
* @param {string} options 加载信息(可选)
* @param {string} el loading挂载的位置,默认挂载在body
*/
open(options, el = null) {
let id = this._loadingList_.length;
if (!el) {
this._parent_ = document.body;
} else if (isHTMLElement(el)) {
this._parent_ = el;
} else {
this._parent_ = document.querySelector(el);
}
if (!options.type) options.type = "service";
this._instance_ = new loadingConstructor({
el: document.createElement("div"),
propsData: options,
});
if (options.type === "service") {
document.body.parentNode.style.overflow = "hidden";
this.overflow = true;
}
this._parent_.appendChild(this._instance_.$el);
this._loadingList_.push({
id: id,
parent: this._parent_,
_instance: this._instance_,
type: options.type,
});
this._parent_ = null;
this._instance_ = null;
return id;
}
/**
*
* @param {number} num loading标识数字
*/
close(id) {
for (let i = 0; i < this._loadingList_.length; i++) {
if (Number(id) === this._loadingList_[i].id || !id) {
this._loadingList_[i].parent.removeChild(
this._loadingList_[i]._instance.$el
);
if (this.overflow && this._loadingList_[i].type === "service") {
document.body.parentNode.style.overflow = "auto";
this.overflow = false;
}
this._loadingList_.splice(i, 1);
}
}
}
}
function isHTMLElement(obj) {
if (obj.nodeType && obj.nodeType === 1) {
return true;
} else {
return false;
}
}
export default new serviceLoading();
指令开启模式
import serviceLoading from "./service";
const directiveLoading = {
name: "loading",
bindFunctions: {
inserted: function(el, binding) {
if (binding.value) {
el.classList.add("ti-loading-parent");
let text = el.getAttribute("ti-loading-text");
let id = serviceLoading.open(
{
type: "directive",
text: text,
},
el
);
el.setAttribute("loadingId", id);
}
},
update: function(el, binding) {
if (!binding.value) {
el.classList.remove("ti-loading-parent");
let id = el.getAttribute("loadingId");
if (id) {
serviceLoading.close(id);
}
} else {
el.classList.add("ti-loading-parent");
let text = el.getAttribute("ti-loading-text");
let id = serviceLoading.open(
{
type: "directive",
text: text,
},
el
);
el.setAttribute("loadingId", id);
}
},
},
};
export default directiveLoading;