前言
模态框是指覆盖在父窗口上的子窗口,但在HTML网页中,并没有父窗口和子窗口的概念。这里是通过可隐藏的遮罩层和一个可隐藏的盒子来实现模态框的效果。
效果演示:
下面开始详细介绍如何实现一个可拖拽的模态框。只对 JS 部分详解,HTML 和 CSS 会放在文章底部的源代码中!
JavaScript详解
整体效果是由以下几个事件构成:
- 点击立即登录按钮,弹出遮罩层和模态框。
- 点击小叉号关闭模态框和遮罩层。
- 鼠标在模态框的标题上按下时,计算鼠标在模态框中的坐标。
- 给整个HTML文档添加鼠标移动事件,通过算法实现模态框跟随鼠标移动。
- 鼠标在HTML文档中松开时,移除HTML文档的鼠标移动事件。
首先获取我们需要操作的元素
let but = document.querySelector('.but') // 立即登录按钮 let shade = document.querySelector('.shade') // 遮罩层 let loginBox = document.querySelector('.login-box') // 模态框 let title = document.querySelector('.title') // 模态框标题:用户登录 let exit = document.querySelector('.exit'); // 小叉号
点击立即登录按钮,弹出遮罩层和模态框。
but.addEventListener('click', function() { shade.style.display = "block"; // 显示遮罩层 loginBox.style.display = "block"; // 显示模态框 });
点击小叉号关闭模态框和遮罩层。
exit.addEventListener('click', function() { shade.style.display = "none"; // 隐藏遮罩层 loginBox.style.display = "none"; // 隐藏遮罩层 });
鼠标在模态框标题上按下时计算鼠标在模态框中的坐标:
title.addEventListener('mousedown', function(event) { let x = event.pageX - loginBox.offsetLeft; let y = event.pageY - loginBox.offsetTop; });
event.pageX 和 event.pageY:获取鼠标在整个页面中的 x 坐标、y 坐标。
loginBox.offsetLeft 和 loginBox.offsetTop:获取模态框距离页面左边和上边的距离。
通过相减的方式计算出鼠标在模态框中的坐标。
鼠标在模态框标题上按下后,再给 document 对象添加鼠标移动事件:
title.addEventListener('mousedown', function(event) { let x = event.pageX - loginBox.offsetLeft; let y = event.pageY - loginBox.offsetTop; document.addEventListener('mousemove', function() { // 鼠标移动后的新坐标减去鼠标在模态框中的坐标,实现模态框跟随鼠标移动 loginBox.style.left = (event.pageX - x)+"px"; loginBox.style.top = (event.pageY - y)+"px"; }); });
这里为什么不把鼠标移动事件给 title ?
如果把鼠标移动事件给 title 的话,鼠标移动过快,会脱离模态框,导致模态框无法跟随移动。
如果想看效果,把这里的 document 换成 title,然后快速拖动即可,这里不做演示!
到这里已经实现了模态框跟随鼠标移动,但当我们松开鼠标后,发现模态框依旧跟随鼠标移动。所以,还需要给 document 添加鼠标松开事件。
title.addEventListener('mousedown', function(event) { let x = event.pageX - loginBox.offsetLeft; let y = event.pageY - loginBox.offsetTop; document.addEventListener('mousemove', loginBoxMove); // 这里需要把鼠标移动事件函数写在外面,因为移除事件监听器时也会用到! function loginBoxMove(event) { loginBox.style.left = (event.pageX - x)+"px"; loginBox.style.top = (event.pageY - y)+"px"; } document.addEventListener('mouseup', function() { document.removeEventListener('mousemove', loginBoxMove); }) });
这里为什么不把鼠标松开事件给 title ?
还是会遇到上述类似的情况,大家可以自行尝试!
源代码
模态框 立即登录用户登录 ×