前言
做过web项目开发的人对layer弹层组件肯定不陌生,作为layUI的一个重要组件,使用简单、接口参数丰富,功能健壮,深受广大开发者的喜爱,作为一个热(经)爱(常)工(划)作(水),喜欢钻研探索技术的程序员(狗),我们自己来实现一个web弹窗/层,一窥layer的本源(/手动滑稽脸),进步,从模仿开始。
首先,模仿layer的部分功能,我们先确定下我们要实现的功能:
msg
1、居中弹出、延时销毁、自适应宽高、支持参数配置
dialog
1、可拖动
2、可最小化、最大化、关闭
3、右下角可对窗口进行缩放
4、支持多个参数配置、扩展
代码编写
大部分的思路都在代码注释里
css样式
复制代码
/* web弹窗 */
.tip-msg {
background-color: rgba(61, 61, 61, 0.93);
color: #ffffff;
opacity: 0;
max-width: 200px;
position: fixed;
text-align: center;
line-height: 25px;
border-radius: 30px;
padding: 5px 15px;
display: inline-block;
}
.tip-shade {
z-index: 9999;
background-color: rgb(0, 0, 0);
opacity: 0.6;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.tip-dialog {
z-index: 10000;
position: fixed;
display: block;
background: #e9e9e9;
border-radius: 5px;
opacity: 0;
border: 1px solid #dad8d8;
box-shadow: 0px 1px 20px 2px rgb(255, 221, 221);
}
.tip-title {
cursor: move;
padding: 5px;
position: relative;
height: 25px;
border-bottom: 1px solid #dad8d8;
user-select: none;
}
.tip-title-text {
margin: 0;
padding: 0;
font-size: 15px;
}
.tip-title-btn {
position: absolute;
top: 5px;
right: 5px;
}
.tip-content {
padding: 8px;
position: relative;
word-break: break-all;
font-size: 14px;
overflow-x: hidden;
overflow-y: auto;
}
.tip-resize {
position: absolute;
width: 15px;
height: 15px;
right: 0;
bottom: 0;
cursor: se-resize;
}
复制代码
js
复制代码
/**
* 自定义web弹窗/层:简易风格的msg与可拖放的dialog
* 依赖jquery
*/
var tip = {
/**
* 初始化
*/
init: function () {
var titleDiv = null;//标题元素
var dialogDiv = null;//窗口元素
var titleDown = false;//是否在标题元素按下鼠标
var resizeDown = false;//是否在缩放元素按下鼠标
var offset = {x: 0, y: 0};//鼠标按下时的坐标系/计算后的坐标
/*
使用 on() 方法添加的事件处理程序适用于当前及未来的元素(比如由脚本创建的新元素)。
问题:事件绑定在div上出现div移动速度跟不上鼠标速度,导致鼠标移动太快时会脱离div,从而无法触发事件。
解决:把事件绑定在document文档上,无论鼠标在怎么移动,始终是在文档范围之内。
*/
//鼠标在标题元素按下
$(document).on("mousedown", ".tip-title", function (e) {
var event1 = e || window.event;
titleDiv = $(this);
dialogDiv = titleDiv.parent();
titleDown = true;
offset.x = e.clientX - parseFloat(dialogDiv.css("left"));
offset.y = e.clientY - parseFloat(dialogDiv.css("top"));
});
//鼠标移动
$(document).on("mousemove", function (e) {
var event2 = e || window.event;
var eveX = event2.clientX; // 获取鼠标相对于浏览器x轴的位置
var eveY = event2.clientY; // 获取鼠标相对于浏览器Y轴的位置
// var height = document.body.clientHeight;//表示HTML文档所在窗口的当前高度;
// var width = document.body.clientWidth;//表示HTML文档所在窗口的当前宽度;
var height = window.innerHeight;//浏览器窗口的内部高度;
var width = window.innerWidth;//浏览器窗口的内部宽度;
//在标题元素按下
if (titleDown) {
//处理滚动条
if (tip.hasXScrollbar()) {
height = height - tip.getScrollbarWidth();
}
if (tip.hasYScrollbar()) {
width = width - tip.getScrollbarWidth();
}
//上边
var top = (eveY - offset.y);
if (top <= 0) {
top = 0;
}
if (top >= (height - dialogDiv.height())) {
top = height - dialogDiv.height() - 5;
}
//左边
var left = (eveX - offset.x);
if (left <= 0) {
left = 0;
}
if (left >= (width - dialogDiv.width())) {
left = width - dialogDiv.width() - 5;
}
dialogDiv.css({
"top": top + "px",
"left": left + "px"
});
}
//在缩放元素按下
if (resizeDown) {
var newWidth = (dialogDiv.resize.width + (eveX - offset.x));
if (dialogDiv.resize.initWidth >= newWidth) {
newWidth = dialogDiv.resize.initWidth;
}
var newHeight = (dialogDiv.resize.height + (eveY - offset.y));
if (dialogDiv.resize.initHeight >= newHeight) {
newHeight = dialogDiv.resize.initHeight;
}
dialogDiv.css("width", newWidth + "px");
dialogDiv.find(".tip-content").css("height", newHeight + "px");
}
});
//鼠标弹起
$(document).on("mouseup", function (e) {
//清空对象
titleDown = false;
resizeDown = false;
titleDiv = null;
dialogDiv = null;
offset = {x: 0, y: 0};
});
//阻止按钮事件冒泡
$(document).on("mousedown", ".tip-title-min,.tip-title-max,.tip-title-close", function (e) {
e.stopPropagation();//阻止事件冒泡
});
//最小化
$(document).on("click", ".tip-title-min", function (e) {
// var height = document.body.clientHeight;//表示HTML文档所在窗口的当前高度;
// var width = document.body.clientWidth;//表示HTML文档所在窗口的当前宽度;
var height = window.innerHeight;//浏览器窗口的内部高度;
var width = window.innerWidth;//浏览器窗口的内部宽度;
var $parent = $(this).parents(".tip-dialog");
//显示浏览器滚动条
document.body.parentNode.style.overflowY = "auto";
//当前是否为最大化
if ($parent[0].isMax) {
$parent[0].isMax = false;
$parent.css({
"top": $parent[0].topMin,
"left": $parent[0].leftMin,
"height": $parent[0].heightMin,
"width": $parent[0].widthMin
});
}
//当前是否为最小化
if (!$parent[0].isMin) {
$parent[0].isMin = true;
$parent[0].bottomMin = $parent.css("bottom");
$parent[0].leftMin = $parent.css("left");
$parent[0].heightMin = $parent.css("height");
$parent[0].widthMin = $parent.css("width");
$parent.css({
"top": "",
"bottom": "5px",
"left": 0,
"height": "30px",
"width": "95px"
});
$parent.find(".tip-title-text").css("display", "none");
$parent.find(".tip-content").css("display", "none");
} else {
$parent[0].isMin = false;
$parent.css({
"top": $parent[0].topMin,
"bottom": $parent[0].bottomMin,
"left": $parent[0].leftMin,
"height": $parent[0].heightMin,
"width": $parent[0].widthMin
});
$parent.find(".tip-title-text").css("display", "block");
$parent.find(".tip-content").css("display", "block");
}
});
//最大化
$(document).on("click", ".tip-title-max", function (e) {
// var height = document.body.clientHeight;//表示HTML文档所在窗口的当前高度;
// var width = document.body.clientWidth;//表示HTML文档所在窗口的当前宽度;
var height = window.innerHeight;//浏览器窗口的内部高度;
var width = window.innerWidth;//浏览器窗口的内部宽度;
var $parent = $(this).parents(".tip-dialog");
//当前是否为最小化
if ($parent[0].isMin) {
$parent[0].isMin = false;
$parent.css({
"top": $parent[0].topMin,
"bottom": $parent[0].bottomMin,
"left": $parent[0].leftMin,
"height": $parent[0].heightMin,
"width": $parent[0].widthMin
});
$parent.find(".tip-title h2").css("display", "block");
}
//当前是否为最大化
if (!$parent[0].isMax) {
//隐藏浏览器滚动条
document.body.parentNode.style.overflowY = "hidden";
$parent[0].isMax = true;
$parent[0].topMin = $parent.css("top");
$parent[0].leftMin = $parent.css("left");
$parent[0].heightMin = $parent.css("height");
$parent[0].widthMin = $parent.css("width");
$parent.css({
"top": 0,
"left": 0,
"height": height - 5 + "px",
"width": width - 5 + "px"
});
} else {
//显示浏览器滚动条
document.body.parentNode.style.overflowY = "auto";
$parent[0].isMax = false;
$parent.css({
"top": $parent[0].topMin,
"left": $parent[0].leftMin,
"height": $parent[0].heightMin,
"width": $parent[0].widthMin
});
}
});
//缩放
$(document).on("mousedown", ".tip-resize", function (e) {
var event1 = e || window.event;
dialogDiv = $(this).parent();
resizeDown = true;
offset.x = e.clientX;
offset.y = e.clientY;
//点击时的宽高
dialogDiv.resize.width = dialogDiv.width();
dialogDiv.resize.height = dialogDiv.find(".tip-content").height();
});
//关闭
$(document).on("click", ".tip-title-close", function (e) {
$(this).parents(".tip-dialog").parent().remove();
//显示浏览器滚动条
document.body.parentNode.style.overflowY = "auto";
});
},
/**
* 是否存在X轴方向滚动条
*/
hasXScrollbar: function () {
return document.body.scrollWidth > (window.innerWidth || document.documentElement.clientWidth);
},
/**
* 是否存在Y轴方向滚动条
*/
hasYScrollbar: function () {
return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);
},
/**
* 计算滚动条的宽度
*/
getScrollbarWidth: function () {
/*
思路:生成一个带滚动条的div,分析得到滚动条长度,然后过河拆桥
*/
var scrollDiv = document.createElement("div");
scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
document.body.appendChild(scrollDiv);
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
document.body.removeChild(scrollDiv);
return scrollbarWidth;
},
/**
* tip提示
* tip.msg("哈哈哈哈哈");
* tip.msg({text:"哈哈哈哈哈",time:5000});
*/
msg: function (setting) {
var time = setting.time || 2000; // 显示时间(毫秒) 默认延迟2秒关闭
var text = setting.text || setting; // 文本内容
//组装HTML
var tip = "
"
+ text +
"
";
//删除旧tip
$(".tip-msg").remove();
//添加到body
$("body").append(tip);
//获取jq对象
var $tip = $(".tip-msg");
//动画过渡
$tip.animate({opacity: 1}, 500);
//计算位置浏览器窗口上下、左右居中
// var height = document.body.clientHeight;//表示HTML文档所在窗口的当前高度;
var width = document.body.clientWidth;//表示HTML文档所在窗口的当前宽度;
var height = window.innerHeight;//浏览器窗口的内部高度;
// var width = window.innerWidth;//浏览器窗口的内部宽度;
width = ((width / 2) - ($tip.css("width").replace("px", "") / 2)) / width;
height = ((height / 2) - ($tip.css("height").replace("px", "") / 2)) / height;
$tip.css({
"top": (height * 100) + "%",
"left": (width * 100) + "%"
});
//延迟删除
setTimeout(function () {