目录
一、需求描述
二、实现效果
三、完整代码
四、实现过程
1、HTML 页面结构
2、CSS 元素样式
3、JavaScript动态控制
(1)获取元素
(2)显示\隐藏遮罩层与模态框
(3)实现模态框拖动效果
一、需求描述
实现一个可以拖拽的模态框;
- 点击打开按钮,显示模态框和遮罩层;
- 点击关闭按钮或遮罩层,隐藏模态框和遮罩层;
- 在模态框的标题栏按下并移动鼠标,模态框跟随鼠标移动(拖拽效果);
二、实现效果
1、点击按钮显示遮罩层和模态框
2、在模态框标题栏按下并移动鼠标,模态框跟随移动
3、点击关闭按钮或者遮罩层隐藏模态框
三、完整代码
【test.html】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>可拖拽的模态框</title>
<style>
* {
margin: 0;
padding: 0;
caret-color: transparent;
}
.open-btn {
display: inline-block;
margin: 60px;
padding: 10px 20px;
font-size: 16px;
color: #fff;
background-color: #409eff;
border: none;
border-radius: 8px;
}
.modal-box {
display: none;
position: fixed;
top: 120px;
left: 60px;
width: 400px;
min-height: 200px;
padding: 10px;
background: #fff;
border-radius: 8px;
box-shadow: 0 0 4px 1px #acacac;
z-index: 99999;
}
.modal-title {
text-align: center;
font-size: 18px;
font-weight: 700;
padding: 20px;
border-bottom: 1px solid #ddd;
cursor: move;
}
.modal-body {
margin: 20px 0;
}
.close-btn {
position: absolute;
top: 6px;
right: 6px;
width: 18px;
height: 18px;
background-image: url("D:\\test\\close.svg");
background-size: cover;
}
.mask {
display: none;
width: 100vw;
height: 100vh;
position: fixed;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, .3);
}
</style>
</head>
<body>
<button class="open-btn">打开模态框</button>
<div class="mask"></div>
<div class="modal-box">
<div class="modal-title">一个可以拖拽的模态框</div>
<div class="modal-body">内容区域不能拖到</div>
<div class="close-btn" />
</div>
</body>
<script>
// 获取打开按钮
var openBtn = document.querySelector(".open-btn");
// 获取模态框
var modalBox = document.querySelector(".modal-box");
// 获取模态框标题
var modalTitle = document.querySelector(".modal-title")
// 获取关闭按钮
var closeBtn = document.querySelector(".close-btn");
// 获取遮罩层
var maskBox = document.querySelector(".mask");
// 2、显示\隐藏遮罩层与模态框
// 2.1、点击打开按钮,显示模态框和遮罩层
openBtn.addEventListener('click', function () {
maskBox.style.display = "block";
modalBox.style.display = "block";
})
// 2.2、点击关闭按钮 或者遮罩层 隐藏模态框和遮罩层
closeBtn.addEventListener('click', function () {
maskBox.style.display = "none";
modalBox.style.display = "none";
})
maskBox.addEventListener('click', function () {
maskBox.style.display = "none";
modalBox.style.display = "none";
})
// 3、拖动模态框
// 3.1 鼠标按下
modalTitle.addEventListener('mousedown', function (e) {
// 获取鼠标起始位置坐标
var mouseX = e.pageX;
var mouseY = e.pageY;
// 模态框的初始左边距 上边距
var modalBoxX = modalBox.offsetLeft;
var modalBoxY = modalBox.offsetTop;
// 3.2 鼠标移动 计算模态框的移动距离
modalTitle.addEventListener('mousemove', moveMouse);
// 3.3 鼠标弹起 移除鼠标移动事件
modalTitle.addEventListener('mouseup', function () {
modalTitle.removeEventListener('mousemove', moveMouse)
})
// 鼠标移动事件回调
function moveMouse(e) {
// 模态框移动的边距 = 模态框的起始边距 + 鼠标的相对移动值;
modalBox.style.left = modalBoxX + (e.pageX - mouseX) + 'px';
modalBox.style.top = modalBoxY + (e.pageY - mouseY) + 'px';
}
})
</script>
</html>
四、实现过程
1、HTML 页面结构
- 一个按钮【button元素】,用来点击显示模态框和遮罩层;
- 一个遮罩层【div元素】;
- 一个模态框【div元素】,其中包含模态框的标题【div元素】、内容【div元素】和关闭按钮【div元素】;
<body>
<button class="open-btn">打开模态框</button>
<div class="mask"></div>
<div class="modal-box">
<div class="modal-title">一个可以拖拽的模态框</div>
<div class="modal-body">内容区域不能拖到</div>
<div class="close-btn" />
</div>
</body>
2、CSS 元素样式
(1)按钮样式
根据自己的喜好自行添加按钮的样式即可;
.open-btn {
display: inline-block;
margin: 60px;
padding: 10px 20px;
font-size: 16px;
color: #fff;
background-color: #409eff;
border: none;
border-radius: 8px;
}
(2)遮罩层样式
- 先不用设置遮罩层的display为none,先让它显示出来,便于观察;
- 设置遮罩层的宽高分别为 100vw 和 100vh ,占满浏览器的整个窗口(根据浏览器窗口大小自适应,始终占满);
- 遮罩层使用固定定位【 position: fixed; 】,使其不受其他元素的位置影响;
.mask {
/* display: none; */
position: fixed;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, .3);
}
(3)模态框样式
- 模态框跟遮罩层一样,不用设置display为none;
- 模态框也使用固定定位【 position: fixed; 】,使其不受其他元素的位置影响;
- 模态框的标题设置cursor属性为move,当鼠标移动到模态框的标题位置时,会显示移动样式;
- 模态框的关闭按钮,使用的是div元素,将其定位到模态框的右上角,并设置其背景为svg图标;
.modal-box {
/* display: none; */
position: fixed;
top: 120px;
left: 60px;
width: 400px;
min-height: 200px;
padding: 10px;
background: #fff;
border-radius: 8px;
box-shadow: 0 0 4px 1px #acacac;
z-index: 99999;
}
.modal-title {
text-align: center;
font-size: 18px;
font-weight: 700;
padding: 20px;
border-bottom: 1px solid #ddd;
cursor: move;
}
.modal-body {
margin: 20px 0;
}
.close-btn {
position: absolute;
top: 6px;
right: 6px;
width: 18px;
height: 18px;
background-image: url("D:\\test\\close.svg");
background-size: cover;
}
3、JavaScript动态控制
(1)获取元素
将页面中需要操作的元素都进行获取;
这里使用的是querySelector()方法来获取元素,是JavaScript中获取dom元素的方式之一;
<script>
// 1、获取页面元素
// 获取打开按钮
var openBtn = document.querySelector(".open-btn");
// 获取模态框
var modalBox = document.querySelector(".modal-box");
// 获取模态框标题
var modalTitle = document.querySelector(".modal-title")
// 获取关闭按钮
var closeBtn = document.querySelector(".close-btn");
// 获取遮罩层
var maskBox = document.querySelector(".mask");
......
</script>
(2)显示\隐藏遮罩层与模态框
在控制遮罩层和模态框的显示与隐藏之前,需要先将其display属性设为none;
.mask {
display: none;
......
}
.modal-box {
display: none;
......
}
根据案例需求,可以知道:
- 遮罩层和模态框的显示与隐藏是同时的,模态框显示则遮罩层显示,模态框隐藏则遮罩层隐藏;
- 当点击【打开模态框】按钮时,进行显示,所以需要给这个按钮注册点击事件,完成相应功能;
- 当点击模态框中的【关闭按钮】或者遮罩层时,进行隐藏,所以需要给关闭按钮和遮罩层都注册鼠标点击事件,完成相应功能;
<script>
......
// 2、显示\隐藏遮罩层与模态框
// 2.1、点击打开按钮,显示模态框和遮罩层
openBtn.addEventListener('click', function () {
maskBox.style.display = "block";
modalBox.style.display = "block";
})
// 2.2、点击关闭按钮 或者遮罩层 隐藏模态框和遮罩层
closeBtn.addEventListener('click', function () {
maskBox.style.display = "none";
modalBox.style.display = "none";
})
maskBox.addEventListener('click', function () {
maskBox.style.display = "none";
modalBox.style.display = "none";
})
......
</script>
(3)实现模态框拖动效果
根据案例需求,分析可知:
- 模态框采用的是固定定位【 position: fixed;】,改变其 top 和 left 值就相当于是在移动了;
- 模态框的移动距离实际就是鼠标的移动距离,加上模态框的起始位置坐标;
- 鼠标的移动距离实际就是鼠标按下的位置,与鼠标移动时位置的差值;
注册 mousedown 事件,鼠标按下,得到鼠标在模态框内的坐标,即起始位置;
注册 mousemove 事件,鼠标移动,获得最新的鼠标位置,计算移动距离;
注册 mouseup 事件,鼠标弹起,停止拖拽,解除鼠标移动事件;
注意:
- mousedown 、mousemove 、mouseup 触发的事件源是模态框的标题栏;
- mousemove、mouseup 是在鼠标按下事件的基础上( 要写到mousedown 事件里面 );
<script>
......
// 3、拖动模态框
// 3.1 鼠标按下
modalTitle.addEventListener('mousedown', function (e) {
// 获取鼠标起始位置坐标
var mouseX = e.pageX;
var mouseY = e.pageY;
// 模态框的初始左边距 上边距
var modalBoxX = modalBox.offsetLeft;
var modalBoxY = modalBox.offsetTop;
// 3.2 鼠标移动 计算模态框的移动距离
modalTitle.addEventListener('mousemove', moveMouse);
// 3.3 鼠标弹起 移除鼠标移动事件
modalTitle.addEventListener('mouseup', function() {
modalTitle.removeEventListener('mousemove', moveMouse)
})
// 鼠标移动事件回调
function moveMouse(e) {
// 模态框移动的边距 = 模态框的起始边距 + 鼠标的相对移动值;
modalBox.style.left = modalBoxX + (e.pageX - mouseX) + 'px';
modalBox.style.top = modalBoxY + (e.pageY - mouseY) + 'px';
}
})
</script>
=========================================================================
每天进步一点点~!
记录下前端这个一个小知识~~!