喏,就是这么一个效果。
具体功能:
- 当消息被触发的时候,会有一个自上而下的淡入过程。
- 在持续了一段时间后会自动的消失,或者是需要用户来手动的点击关闭按钮。
- 在消息消失的时候,会有一个自下而上的淡出过程。
- 消息是可以叠加弹出的,最新的消息会排在消息列表的最后面。
- 当前面的消息消失后,后面的消息会有一个向上滑动效果。
message.html
<!-- message.html -->
<!-- 这个css是我引用阿里的一些字体图标,请戳: https://www.iconfont.cn/ -->
<link rel="stylesheet" href="http://at.alicdn.com/t/font_1117508_wxidm5ry7od.css">
<link rel="stylesheet" href="./message.css">
<script src="./message.js"></script>
<!-- 消息外层容器,因为消息提醒基本上是全局的,所以这里用id,所有的弹出消息都是需要插入到这个容器里边的 -->
<div id="message-container">
<div class="message">
<!-- 消息图标 icon icon-success对应我的阿里字体图标的font-class -->
<div class="type icon icon-success"></div>
<!-- 消息文本 -->
<div class="text">这是一条正经的消息~</div>
<!-- 关闭按钮 -->
<div class="close icon icon-close"></div>
</div>
<div class="message">
<div class="type icon icon-error"></div>
<div class="text">这是一条正经的消息~</div>
</div>
</div>
message.css
#message-container {
position: fixed;
left: 0;
top: 0;
right: 0;
z-index: 10000;
/* 采用flex弹性布局,让容器内部的所有消息可以水平居中,还能任意的调整宽度 */
display: flex;
flex-direction: column;
align-items: center;
}
#message-container .message {
background: #fff;
margin: 10px 0;
padding: 0 10px;
height: 40px;
box-shadow: 0 0 10px 0 #ccc;
font-size: 14px;
border-radius: 3px;
/* 让消息内部的三个元素(图标、文本、关闭按钮)可以垂直水平居中 */
display: flex;
align-items: center;
}
#message-container .message .text {
color: #333;
padding: 0 20px 0 5px;
}
#message-container .message .close {
cursor: pointer;
color: #999;
}
/* 给每个图标都加上不同的颜色,用来区分不同类型的消息 */
#message-container .message .iconicon-info {
color: #0482f8;
}
#message-container .message .iconicon-error {
color: #f83504;
}
#message-container .message .iconicon-success {
color: #06a35a;
}
#message-container .message .iconicon-warning {
color: #ceca07;
}
#message-container .message .iconicon-loading {
color: #0482f8;
}
@keyframes message-move-in {
0% {
/* 前边分析过了,弹出动画是一个自上而下的淡入过程 */
/* 所以在动画初始状态要把元素的不透明度设置为0,在动画结束的时候再把不透明度设置1,这样就会实现一个淡入动画 */
opacity: 0;
/* 那么“自上而下”这个动画可以用“transform”变换属性结合他的“translateY”上下平移函数来完成 */
/* translateY(-100%)表示动画初始状态,元素在实际位置上面“自身一个高度”的位置。 */
transform: translateY(-100%);
}
100% {
opacity: 1;
/* 平移到自身位置 */
transform: translateY(0);
}
}
#message-container .message.move-in {
/* animation属性是用来加载某个动画规则 请参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation */
animation: message-move-in 0.3s ease-in-out;
}
@keyframes message-move-out {
0% {
opacity: 1;
transform: translateY(0);
}
100% {
opacity: 0;
transform: translateY(-100%);
}
}
#message-container .message.move-out {
animation: message-move-out 0.3s ease-in-out;
/* 让动画结束后保持结束状态 */
animation-fill-mode: forwards;
}
message.js
class Message {
/**
* 构造函数会在实例化的时候自动执行
*/
constructor() {
const containerId = 'message-container';
// 检测下html中是否已经有这个message-container元素
this.containerEl = document.getElementById(containerId);
if (!this.containerEl) {
// 创建一个Element对象,也就是创建一个id为message-container的dom节点
this.containerEl = document.createElement('div');
this.containerEl.id = containerId;
// 把message-container元素放在html的body末尾
document.body.appendChild(this.containerEl);
}
}
show({type = 'info', text = ''}) {
// 创建一个Element对象
let messageEl = document.createElement('div');
// 设置消息class,这里加上move-in可以直接看到弹出效果
messageEl.className = 'message move-in';
// 消息内部html字符串
messageEl.innerHTML = `
<span class="iconfont iconicon-${type}"></span>
<div class="text">${text}</div>
<div class="close icon icon-close"></div>
`;
// 追加到message-container末尾
// this.containerEl属性是我们在构造函数中创建的message-container容器
this.containerEl.appendChild(messageEl);
setTimeout(() => {
// 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下
messageEl.className = messageEl.className.replace('move-in', '');
// 增加一个move-out类
messageEl.className += 'move-out';
// 这个地方是监听动画结束事件,在动画结束后把消息从dom树中移除。
// 如果你是在增加move-out后直接调用messageEl.remove,那么你不会看到任何动画效果
messageEl.addEventListener('animationend', () => {
// Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除!
messageEl.remove();
});
}, 1500);
}
}
调用
const message = new Message();
message.show({type: 'success', text: '这是成功的消息' })
本文原创作者:Laravuel,原文链接:https://www.jianshu.com/p/230810ef6543