此处不考虑兼容性问题,因为在IE8及其以下的版本中不支持事件对象的page坐标系列。所以我们直接使用元素的page系列坐标。
一、原生JS实现
需求:
// 1.点击登录按钮,让登录盒子显示在页面上,同时出现遮罩层
// 2.点击登录盒子的关闭按钮,登录盒子消失
// 3.登录盒子可拖拽
思路分析:这里的重点是第三步登录盒子的可拖拽,具体思路如下图:
我们解决盒子拖拽的思路就是:因为红线的距离是一直不变的,所以,可以先求出来定义为x,y;而在整个页面中注册鼠标移动事件,这样就可以求出在页面上触发点的e.pageX,利用e.pageX - x 这样就可以求出盒子的offsetLeft值,这个值就是元素的left值,最后将这个值赋给元素的left属性就可以了。
当然里面有两个问题:
1.元素本身有margin属性?
2.给页面添加了一个鼠标移动事件,那么在页面上的任何位置移动,都会让login盒子可拖拽吗?
先说第一个问题:
当元素有margin属性的时候,我们如果直接将offsetLeft = e.pageX - 红线的距离赋值给元素的left属性,此时定位的left属性与margin-left的值会发生叠加计算得到一个新的值,此时才是盒子距离页面左边的位置。所以我们要将margin的值也考虑到计算进去,最后计算出来的offsetLeft的值就是盒子的真实距离。
offsetLeft = e.pageX - (-256px)(magin-left的值) - 红线的位置 ;整体赋值给left,因为页面又有:
margin-left = -256px; 所以两者叠加后就是真正的offsetLeft的值。
再说第二个问题:
2.给页面添加了一个鼠标移动事件,那么在页面上的任何位置上移动,都会让login盒子可拖拽吗?换句话说,因为在整个页面注册了onmousemove事件,那么在整个页面移动,盒子都会拖动起来吗?
肯定不是的,这是因为我们注册的事件的是又两个:
第一个:给login盒子的头部区域title,注册了一个鼠标按下事件。
第二个:在第一个事件函数的里面,又注册了一个整个页面的鼠标移动事件。
也就可以这样理解:只有我按下登录盒子的头部后,并且鼠标停留在上面,此时就可以拖动盒子在整个页面上移动。
代码实现:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
/* 登录按钮 */
.login-header {
width: 100%;
text-align: center;
height: 30px;
font-size: 24px;
line-height: 30px;
}
html, body, ul, li, ol, dl, dt, dd, div, p, span, h1, h2, h3, h4, h5, h6, a {
padding: 0px;
margin: 0px;
}
/* 登录盒子 */
.login {
width: 512px;
position: absolute;
border: #ebebeb solid 1px;
height: 280px;
left: 50%;
right: 50%;
background: #ffffff;
box-shadow: 0px 0px 20px #ddd;
z-index: 9999;
margin-left: -256px;
margin-top: 140px;
/* 登录盒子的显示模式默认是不显示 */
display: none;
}
.login-title {
width: 100%;
margin: 10px 0px 0px 0px;
text-align: center;
line-height: 40px;
height: 40px;
font-size: 18px;
position: relative;
cursor: move;
}
.login-input-content {
margin-top: 20px;
}
.login-button {
width: 50%;
margin: 30px auto 0px auto;
line-height: 40px;
font-size: 14px;
border: #ebebeb 1px solid;
text-align: center;
}
/* 遮罩层的设计 */
.login-bg {
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: #000000;
opacity: 0.3;
display: none;
}
a {
text-decoration: none;
color: #000000;
}
.login-button a {
display: block;
}
.login-input input.list-input {
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: #ebebeb 1px solid;
text-indent: 5px;
}
.login-input {
overflow: hidden;
margin: 0px 0px 20px 0px;
}
.login-input label {
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 14px;
}
/* 登录关闭按钮 */
.login-title span {
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background: #ffffff;
border: #ebebeb solid 1px;
width: 40px;
height: 40px;
border-radius: 20px;
}
</style>
</head>
<body>
<!-- 登录按钮 -->
<div class="login-header">
<a id="link" href="javascript:void(0);">点击,弹出登录框</a>
</div>
<!-- 登录的盒子 -->
<div id="login" class="login">
<div id="title" class="login-title">登录会员
<span>
<a id="closeBtn" href="javascript:void(0);" class="close-login"> 关闭</a>
</span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登录密码:</label>
<input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
</div>
<!-- 遮罩层是整个body的背景 -->
<div id="bg" class="login-bg"></div>
<script>
//需求:
// 1.点击登录按钮,让登录盒子显示在页面上,同时出现遮罩层
// 2.点击登录盒子的关闭按钮,登录盒子消失
// 3.登录盒子可拖拽
//获取元素
var loginBtn = document.getElementById("link"); //登录按钮
var login = document.getElementById("login"); //登录盒子
var closeLogin = document.getElementsByClassName("close-login")[0]; //关闭登录盒子的按钮
var bg = document.getElementById('bg'); //遮罩层
var title = document.getElementById('title'); //头部
loginBtn.onclick = function(){
//点击登录按钮的时候,弹出登录框
login.style.display= "block";
//打开遮罩层
bg.style.display = "block";
}
closeLogin.onclick = function(){
//点击关闭按钮,登录框隐藏
login.style.display = "none";
//打开遮罩层
bg.style.display = "none";
}
//可以按住拖拽的部分title
//当然也可以给整登录盒子 login盒子注册一个按下事件
title.onmousedown = function(e){
//1.获取红线的距离
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
//给整个页面添加鼠标移动事件
document.onmousemove = function (e){
//计算此时登录盒子在页面当中的位置
login.style.left = e.pageX - x + 256 + "px";
login.style.top = e.pageY - y - 140 + "px";
}
}
title.onmouseup = function(){
//当鼠标弹起时将页面的鼠标移动事件清空就可以了
document.onmousemove = null;
}
</script>
</body>
</html>
二、jQuery代码实现:
思路都是一样,只需要将上面的代码翻译为jQuery的代码来实现就可以了。
<script src="jquery-1.12.4.js"></script>
<script>
$(function(){
$('#link').on("click",function(){
$('#login').show();
$('#bg').show();
})
$('.close-login').on('click',function(){
$('#login').hide();
$('#bg').hide();
})
$('#title').on('mousedown',function(event){
//计算盒子在页面上的位置
var offset_x = $('#login').offset().left;
var offset_y = $('#login').offset().top;
//获取鼠标在login盒子里面的触发点
var mouse_x = event.pageX;
var mouse_y = event.pageY;
$("body").on('mousemove',function(e){
console.log(e.target);
/* 计算鼠标移动了的位置 */
var _x = e.pageX - mouse_x;
var _y = e.pageY - mouse_y;
/* 设置移动后的元素坐标 */
//这里的256是元素自身带有的margin-left的值,下面的140同理
var now_x = (offset_x + _x + 256 ) + "px";
var now_y = (offset_y + _y - 140) + "px";
$('#login').css('left',now_x);
$('#login').css('top',now_y);
})
})
$('#title').on('mouseup',function(){
//这里利用事件的解绑
$('body').off('mousemove');
})
})
</script>
利用jQuery实现的思路与JS大体相仿,这里就不多做解释.
三、利用H5里面的托和放来实现
注意:在网页中,图片可以托拽,其他的默认不能托拽。如果一定要拖拽,要在标签加上,加一个行内属性 draggable=”true”,这个属性默认是false。
以及拖拽的三个事件:
//拖拽开始触发的事件
元素.ondragstart = function () { }
//拖拽中触发的事件
元素.ondrag = function () { }
//拖拽结束事件
box.ondragend = function () { }
利用上面的知识将登陆框的可拖拽利用H5实现:因为样式与页面结构是一模一样的,所以这里只有js的代码。
<script>
var loginBtn = document.getElementById("link"); //登录按钮
var closeLogin = document.getElementsByClassName("close-login")[0]; //关闭登录盒子的按钮
var bg = document.getElementById('bg'); //遮罩层
var title = document.getElementById('title'); //头部
//利用H5的托和放来实现登录盒子的拖拽功能
var login = document.getElementById("login"); //登录盒子
//定义x,y来保存鼠标在盒子里的位置
var x,y;
loginBtn.onclick = function(){
//点击登录按钮的时候,弹出登录框
login.style.display= "block";
//打开遮罩层
bg.style.display = "block";
}
closeLogin.onclick = function(){
//点击关闭按钮,登录框隐藏
login.style.display = "none";
//打开遮罩层
bg.style.display = "none";
}
//盒子拖拽开始事件
login.ondragstart = function(e) {
//获取鼠标在盒子里面的位置
x = e.pageX - login.offsetLeft;
y = e.pageY - login.offsetTop;
// login.style.cursor = "crosshair";
}
//盒子拖拽中的事件
login.ondrag = function(){
//测试用,也可以不用
console.log('.....');
// login.style.cursor = "crosshair";
}
//盒子拖拽结束事件
login.ondragend = function(e) {
//盒子最终的位置
login.style.left = e.pageX - x + 256 + 'px';
login.style.top = e.pageY - y - 140 + 'px';
// login.style.cursor = "crosshair";
}
</script>
但是有一个bug,鼠标的样式在拖拽过程中一直是禁止的样式。
未完待续!!!