鼠标拖拽移动子窗体的JS实现


Posted in Javascript onFebruary 25, 2014

1.子窗体

在设计网站的时候,我们需要设计一些模态的子窗体,比如

鼠标拖拽移动子窗体的JS实现

这一步很容易实现,只需要div+css就ok了,请看代码:

    <div class="modal-background"></div>
    <div class="modal-window">
        <div class="head">
            <center>点住着块区域可以改变我的位置</center>
        </div>
    </div>

.modal-background
{
    background-color: #999999;
    bottom: 0;
    left: 0;
    opacity: 0.3;
    position: fixed;
    right: 0;
    top: 0;
    z-index: 1100;
}
.modal-window
{
    background-color: #FFFFFF;
    border: 1px solid #6B94AD;
    box-shadow: 5px 5px 5px #6B94AD;
    font-family: 'Microsoft YaHei';
    font-size: 12px;
    height: 120px;
    left: 50%;
    margin-left: -160px;
    margin-top: -160px;
    opacity: 1;
    position: fixed;
    top: 50%;
    width: 320px;
    z-index: 1110;
}
    .modal-window .head
    {
        height: 25px;
        color: #fff;
        font-weight: 600;
        background-image: -moz-linear-gradient(top, #4A8CC5, #2963A5); /* Firefox */
        background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #4A8CC5), color-stop(1, #2963A5)); /* Saf4+, Chrome */
        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4A8CC5', endColorstr='#2963A5', GradientType='0'); /* IE*/
    }
        .modal-window .head center
        {
            padding-top: 2px;
        }

加上上述html和css就可以很容易实现上述模态窗体的效果。其中left: 50%;top: 50%; margin-left: -160px; margin-top: -160px;是为了实现这个模态窗体的居中效果。

当然,模态窗体的大小在样式类.modal-window中是固定写好的了,这并不是说不可修改模态窗体的大小,比如我写如代码:

    <div class="modal-background"></div>
    <div class="modal-window list-window">
        <div class="head">
            <center>点住着块区域可以改变我的位置</center>
        </div>
    </div>

在第二行代码中追加了.list-window这个样式类来覆盖.modal-window类中的大小和位置,但同时保证模态窗体居中显示

.list-window
{
    width:600px;
    height:400px;
    margin-left:-300px;
    margin-top:-200px;
}

如图

鼠标拖拽移动子窗体的JS实现

可以看得出来,这一步的实现是非常简单的,掌握几个关键行的css属性就"完虐"这个模态子窗体,各类其它的模态子窗体可以举一反三咯。

2.当鼠标点住子窗体的头部时,如何实现子窗体的拖拽移动呢?当引入jQ后,我们只需要很少的脚本就搞定这个小功能。不信我们看

var left, top, $this;
$(document).delegate('.modal-window .head', 'mousedown', function (e) {
    left = e.clientX, top = e.clientY, $this = $(this).css('cursor', 'move');
    this.setCapture ? (
    this.setCapture(),
    this.onmousemove = function (ev) { mouseMove(ev || event); },
    this.onmouseup = mouseUp
    ) : $(document).bind("mousemove", mouseMove).bind("mouseup", mouseUp);
});
function mouseMove(e) {
    var target = $this.parents('.modal-window');
    var l = Math.max((e.clientX - left + Number(target.css('margin-left').replace(/px$/, '')) || 0), -target.position().left);
    var t = Math.max((e.clientY - top + Number(target.css('margin-top').replace(/px$/, '')) || 0), -target.position().top);
    l = Math.min(l, $(window).width() - target.width() - target.position().left);
    t = Math.min(t, $(window).height() - target.height() - target.position().top);
    left = e.clientX;
    top = e.clientY;
    target.css({ 'margin-left': l, 'margin-top': t });
}
function mouseUp(e) {
    var el = $this.css('cursor', 'default').get(0);
    el.releaseCapture ?
    (
        el.releaseCapture(),
        el.onmousemove = el.onmouseup = null
    ) : $(document).unbind("mousemove", mouseMove).unbind("mouseup", mouseUp);
}

这段代码非常简短,能否在各种浏览器中很流畅的运行。

其实它的实现原理非常简单,大致分为三步:

①当鼠标在模态窗体头部点下(mousedown)时,立即给document绑定mousemove和mouseup事件

②当鼠标没有弹起时(没有mouseup)时,若鼠标在窗体内移动时,激活mouseMove函数,通过计算鼠标移动的距离来及时整个窗体的位置移动。

③当鼠标弹起(mouseup)时,调用mouseUp事件,将document上绑定的mousemove事件和mouseup事件解除绑定。

整个过程的原理就是:当鼠标mousedown时,鼠标的移动事件转移到document上来,通过鼠标在document上的移动事件来对整个窗体进行处理。

另外,在mouseMove中有个小技巧,就是全局的left,top变量记录上一次鼠标停止时的位置,然后下一次移动时鼠标的位置与left,top变量进行对比来确定鼠标移动了多少距离,来对整个模态子窗体做出相应的位置移动即可。

经过这一段代码的分析,发现鼠标移动窗体乃至document上的任何元素都是相当easy的

比如,如果想要通过拖拽来改变窗体的大小,一样我们只需要在mouseMove事件处理函数中调整窗体的大小就ok了,是不是又发现自己有多学会了一招,又精进了一小步呢?

有人会问setCapture和releaseCapture分别都是干什么的呢?其实这是为了兼容IE,仅有IE才有这俩函数,在此鄙视IE。setCapture可以让当前元素捕获鼠标的所有事件,如果不使用它们,可能不兼容IE浏览器哦。

Javascript 相关文章推荐
js 自制滚动条的小例子
Mar 16 Javascript
JS操作select下拉框动态变动(创建/删除/获取)
Jun 02 Javascript
Textarea根据内容自适应高度
Oct 28 Javascript
jquery的ajax跨域请求原理和示例
May 08 Javascript
使用focus方法让光标默认停留在INPUT框
Jul 29 Javascript
JavaScript数组前面插入元素的方法
Apr 06 Javascript
jQuery中的select操作详解
Nov 29 Javascript
js实现楼层导航功能
Feb 23 Javascript
原生js实现旋转木马轮播图效果
Feb 27 Javascript
Vue中jsx不完全应用指南小结
Nov 01 Javascript
JavaScript实现电灯开关小案例
Mar 30 Javascript
JavaScript 实现拖拽效果组件功能(兼容移动端)
Nov 11 Javascript
js判断为空Null与字符串为空简写方法
Feb 24 #Javascript
JS清空多文本框、文本域示例代码
Feb 24 #Javascript
脚本合并提升javascript性能示例
Feb 24 #Javascript
动态加载脚本提升javascript性能
Feb 24 #Javascript
巧用局部变量提升javascript性能
Feb 24 #Javascript
javascript中的原型链深入理解
Feb 24 #Javascript
JSONP获取Twitter和Facebook文章数的具体步骤
Feb 24 #Javascript
You might like
了解咖啡雨林联盟认证 什么是雨林认证 雨林认证是什么意思
2021/03/05 新手入门
深入php内核之php in array
2015/11/10 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
js 兼容多浏览器的回车和鼠标焦点事件代码(IE6/7/8,firefox,chrome)
2010/04/14 Javascript
JS刷新当前页面的几种方法总结
2013/12/24 Javascript
javascript的document.referrer浏览器支持、失效情况总结
2014/07/18 Javascript
node.js实现BigPipe详解
2014/12/05 Javascript
浅谈Javascript数组索引
2015/07/29 Javascript
浅析Node.js 中 Stream API 的使用
2015/10/23 Javascript
常用javascript表单验证汇总
2020/07/20 Javascript
Javascript将字符串日期格式化为yyyy-mm-dd的方法
2016/10/27 Javascript
jQuery实现手机上输入后隐藏键盘功能
2017/01/04 Javascript
angularjs2中父子组件的数据传递的实例代码
2017/07/05 Javascript
微信小程序时间控件picker view使用详解
2018/12/28 Javascript
js tab栏切换代码实例解析
2019/09/03 Javascript
js模拟F11页面全屏显示
2019/09/17 Javascript
node.js中事件触发器events的使用方法实例分析
2019/11/23 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
[57:09]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第一场 1月26日
2021/03/11 DOTA
Python Sleep休眠函数使用简单实例
2015/02/02 Python
Python与shell的3种交互方式介绍
2015/04/11 Python
CentOS下Python3的安装及创建虚拟环境的方法
2018/11/28 Python
详解Python网络框架Django和Scrapy安装指南
2019/04/01 Python
python cumsum函数的具体使用
2019/07/29 Python
python 使用递归回溯完美解决八皇后的问题
2020/02/26 Python
Keras实现将两个模型连接到一起
2020/05/23 Python
关于keras中keras.layers.merge的用法说明
2020/05/23 Python
浅谈TensorFlow之稀疏张量表示
2020/06/30 Python
div或img图片高度随宽度自适应的方法
2020/02/06 HTML / CSS
英国最大的汽车交易网站:Auto Trader UK
2016/09/23 全球购物
CLR与IL分别是什么含义
2016/08/23 面试题
abstract 可以和 virtual 一起使用吗?可以和 override 一起使用吗?
2012/10/15 面试题
趣味体育活动方案
2014/02/08 职场文书
乡镇党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
2016年全国爱眼日宣传教育活动总结
2016/04/05 职场文书
只用20行Python代码实现屏幕录制功能
2021/06/02 Python