制作一个可拖动的html对话框

本文介绍如何不依赖jQuery UI,手动创建一个具有拖动功能的HTML对话框。通过分析事件处理,解决拖动过程中遇到的问题,如拖动速度过快导致的响应延迟,以及非对话框区域启动拖动等。文中提供了详细的步骤和代码示例来实现这一功能。
部署运行你感兴趣的模型镜像

制作对话框,最简单的方式是使用jQuery的ui插件,一行代码就搞定。

$("<div>我是一个对话框</div>").dialog(); 

但是前提是需要引入jquery和ui库:

<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"/>
<script src="http://code.jquery.com/jquery-1.11.2.min.js">
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js">

jQuery UI的js库是比较庞大的,上面的版本需要约80kb,下载和解析都会比较花时间(当然可以进行用ui库的定制版)。为了一个对话框,动用了一个比较大的框架,然后使用了一小部分功能,有点不太值得。其实我们可以自己动手写一个有拖动效果的效果的对话框,不需要借助jQuery UI.

一、需求和效果

在页面点击合作协议时,弹出合作协议的对话框(页面添加了遮罩效果),并且可以用鼠标进行拖动。
效果展示

二、原理分析

主要利用mousemove事件,当鼠标移动的时候让对话框跟随鼠标进行移动。当鼠标按下时,响应mousedown事件,记录下当前需要进行拖动的元素,并保存到一个变量,mousemove时对该元素进行移动,mouseup时,释放掉那个变量

三、实现

首先,写好html内容,并调好样式:置为fixed,页面居中。(css代码略)

<div class='agreement-dlg'>
    <h3>合作模式</h3>
    <p>1. ...</p>
</div>

然后,写事件响应,响应三个鼠标事件。

//将所有的操作,封装到一个函数
dragAndDrop($(".agreement-dlg"));

//传进一个参数,表示哪个页面元素要进行拖动
function dragAndDrop($element){
    //用一个isDragging变量表示当前是否在拖动
    var isDragging = false;

    //响应事件,将三个事件都用同一个handler
    function handleEvent(event){
        switch(event.type){
            //鼠标按下时,置标志位为true
            case: 'mousedown':
                isDragging = true;
                break;
            case: 'mouseup':
                isDragging = false;
                break;
            //一但鼠标进行移动,更新element的位置
            case: 'mousemove':
                if(isDragging){
            //使用jQuery的css设置left和top值有很好的跨浏览器兼容性
                    $element.css({left: event.clientX, top: event.clientY});
                }
                break;
        }
        var element = $element.get(0);
        element.onmousemove = handleEvent;
        element.onmouseup   = handleEvent;
        element.onmousedown = handleEvent;
    }
}

考虑到mousemove事件发生较为频繁,可将第三个case置为第一位,提高程序的效率。

1. 第一个问题

当你把代码敲进去实现时,会发现有一个问题,就是在设置lefttop时,是以鼠标在当前页面的的x/y值,所以会将对话框的左上角设置成鼠标每次按下去的位置。因此在设置lefttop时,需要减去偏差值,即对话框的左上角距离鼠标点击位置的偏差。响应mousemove的代码改成:

$element.css({left: event.clientX - element.offsetX, 
               top: event.clientY - element.offsetY});
2. 第二个问题

当鼠标拖动得很迅速的时候,你会发现,对话框跟不上,掉队了。掉队了之后,由于鼠标已经在对话框之外,因此不会再响应mousemove事件了。所以不能将handler绑定在对话框上面,一但拖动过快,鼠标超出了对话框的范围,就没有拖动效果了。
回顾DOM的事件冒泡,我们知道,发生在元素节点(elementNode)的事件会不断延着父节点一直冒泡到document节点。因此,我们将事件监听绑定到document,在document上做响应,而不是element,因此将最后面的事件绑定改为:

var doc = window.document;
doc.onmousemove = handleEvent;
doc.onmousedown = handleEvent;
doc.onmouseup = handleEvent;

这样就可以解决拖动过快,鼠标超出响应范围的问题。

四、继续完善

我们还需要一个关闭对话框的按钮,加在对话框的顶部。

<div class='agreement-dlg'>
    <--添加一个对话框,使用unicode的╳符号,不需要使用图片或者icon font-->
    <div class='title-bar'>
        <a href="#nogo" class="close">╳</a>
    </div>
    <div class='_body'>
        <h3>合作模式<h3>
        <p>内容</p>
    </div>
</div>

然后在响应关闭按钮的函数里,将相关事件的handler清空,同时将对话框关闭。

$element.remove();
var doc = window.document;
doc.onmousemove = null;
doc.omousedown = null;
doc.onmouseup = null;

如果不将事件的响应函数清除,那么关闭对话框之后,三个鼠标事件仍然在监听,因为我们是绑到document上的。

最后,细心的你会发现上面的实现还有问题

第三个问题

当鼠标按下的时候,需要判断点击的对象是不是相应的对话框,如果不是的话,不进行拖动。使用上面的代码,如果点击的地方是在页面的其它位置,对话框也会有拖动效果,因此需要对操作的对象进行判断。
首先,对话框添加一个moveclass

<div class='agreement-dlg move'>

然后,用一个变量存储当前拖动的对象

//不需要传参数
function dragAndDrop(){
    //用一个变量表示当前需要拖动的对象
    var draggingObj = null;
    function handleEvent(event){
        switch(event.type){
            case: 'mousedown':
            //使用jQuery的closest函数找到最近的含有move的父元素或当前元素
            //如果是用dom原生的event,注意浏览器兼容性
                draggingObj = $(event.target || event.srcElement ).closest(".move");
                break;
            case: 'mouseup':
                draggingObj = null;
                break;
            case: 'mosemove':
                if(draggingObj) ...//剩下的一样

通过这样的方式,我们只需要将页面中需要拖动的元素添加一个move的class,就能够实现该元素的拖动效果,但注意该元素的position要设为fixed或者abosolute.

参考:
《Javascript高级程序设计》第十二章《事件》(professional javascript for web developers)

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值