原生实现简单的微信loading提示控件

110 阅读2分钟

思路: 实现一个toast类,可采用链式方式进行调用

实现效果如下:

image.png image.png

实例化一个toast对象,可实现链式调用,如: 实现一个toast对象, 先执行showloading方法打印出加载中,然后三秒后执行打印‘加载成功’文案

toast.showloading('加载中').delay(3000).msgsucc('加载成功');

一般的函数调用和链式调用的区别:链式调用完方法后,return this返回当前调用方法的对象。

class Toast {
  constructor() {
    this.queue = Promise.resolve();
  }
  delay(time) {
    this.queue = this.queue.then(() => {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve();
        }, time)
      })
    }).catch(err => {
         console.log('出错');
    })
    return this;
  }
  showloading(msg) {
      this.queue = this.queue.then(() => {
          console.log(msg);
       })
      return this;
  }
  msgsucc(msg) {
      this.queue = this.queue.then(() => {
          console.log(msg);
       })
      return this;
  }
  msgerror(msg) {
      this.queue = this.queue.then(() => {
          console.log(msg);
       })
  }
  
}
var toast = new Toast();
toast.showloading('加载中').delay(3000).msgsucc('加载成功');

这就是实例化一个对象,并能实现链式调用,下面利用这种方式实现一个简易版的loading消息控件

// 创建dom元素
function creatElement(tagName, options) {
	var elem = document.createElement(tagName);
	if (options.parent) {
		options.parent.appendChild(elem);
	}
	if (options.attrs) {
		for (var name in options.attrs) {
			elem.setAttribute(name, options.attrs[name]);
		}
	}
	if (options.classes) {
		var clazz = options.classes.replace('/^\\s+$/g', ' ').split(' ');
		for (var i = 0; i < clazz.length; i++) {
			if (clazz[i]) {
				elem.classList.add(clazz[i]);
			}
		}
	}
	if (options.styles) {
		for (var key in options.styles) {
			elem.style[key] = options.styles[key];
		}
	}
	if (options.innerText) {
		elem.innerText = options.innerText;
	}
	if (options.children) {
		options.children.forEach(item => {
			elem.appendChild(item);
		});
	}
	return elem;
}

function removeElement(elem) {
	if (elem && elem.parentNode) {
		elem.parentNode.removeChild(elem);
	}
}
// 居中
function fnCenterView(view) {
	var objh = view.offsetHeight / 2;
	var objw = view.offsetWidth / 2;
	view.style.top = "-webkit-calc(45% - " + objh + "px)";
	view.style.top = "-webkit-calc(50% - " + objw + "px)";
	view.style.top = "calc(45% - " + objh + "px)";
	view.style.left = "calc(50% - " + objw + "px)";
}
class ToastView {
	constructor() {
		var body = document.body;
		this.view = creatElement('div', {
			parent: body,
			classes: 'ciel_msgview info'
		});
		this.loading = null;
		this.succ = null;
		this.message = null;
	}
	showloading(msg) {
		this.loading = creatElement('div', {
			parent: this.view,
			classes: 'ciel_msgview_loading'
		});
		// 实现加载动画效果
		for (let i = 0; i < 13; i++) {
			let loadingChild = creatElement('div', {
				parent: this.loading,
				styles: {
					'-webkit-transform': 'rotate(' + i * 30 + 'deg) translate(0, -142% )',
					'-webkit-animation-delay': -1 + 0.0833 * i + 's'
				}
			});
		}
		this.message = creatElement('div', {
			parent: this.view,
			innerText: msg || '加载中',
			classes: 'ciel_msgview_msg'
		});
		fnCenterView(this.view);
		return this;
	}
	hide(delay = 100, callback) {
		setTimeout(() => {
			removeElement(this.view);
			callback ? callback() : '';
		}, delay);
	}
	msgsucc(msg) {
		removeElement(this.loading);
		removeElement(this.loading);
		var succ = this.succ =  creatElement('div', {
			parent: this.view,
			classes: 'ciel_msgview_succss'
		});
		let loadingChild = creatElement('div', {
			parent: succ
		});
		if(this.message) {
			this.message.innerText = msg || '成功';
		}
		return this;
	}
}
var toast = new ToastView();
let msgview = toast.showloading('正在加载...');
setTimeout(() => {
	msgview.msgsucc('加载完成').hide(500);
},2000)

样式实现

.ciel_msgview {
	background-color: black;
	position: fixed;
	top: 50%;
	left: 0%;
	border-radius: 3px;
	background-color: rgba(0, 0, 0, 0.7);
	max-width: 80%;
	z-index: 99999;
	opacity: 0;
	transition: transform 0.2s, opacity 0.2s;
	word-break: break-all;
	transform: scale(0.8, 0.8);
	}
			
.ciel_msgview {
	opacity: 1;
	transform: scale(1, 1);
}
			
.ciel_msgview_loading,.ciel_msgview_succss{
	width: 100px;
	height: 100px;
}
.ciel_msgview_loading div {
	width: 3px;
	height: 9px;
	background-color: white;
	position: absolute;
	left: 48%;
	top: 35px;
	opacity: 0;
	border-radius: 3px;
        animation: loading_fade 1s linear infinite;
}
			
@keyframes loading_fade {
	from {
		opacity: 1;
	}
			
	to {
		opacity: 0.25;
	}
}
			
@keyframes loading_fade {
	from {
		opacity: 1;
	}
			
	to {
		opacity: 0.25;
	}
}
.ciel_msgview_msg {
	width: 100%;
	color: white;
	position: absolute;
	bottom: 10px;
	font-size: 14px;
	text-align: center;
	left: 0;
				
}
.ciel_msgview_succss div {
  width: 48px;
    height: auto;
    line-height: 26px;
    position: relative;
    cursor: pointer;
}

.ciel_msgview_succss div::before {
      position: absolute;
      content: " ";
      width: 27px;
      height: 45px;
      transform: rotate(45deg);
      border-right: 5px solid #fff;
      border-bottom: 5px solid #fff;
      top: 3%;
      left: 73%;
}