Web开发:一个可拖拽的模态框(HTML、CSS、JavaScript)

目录

一、需求描述

二、实现效果

三、完整代码

四、实现过程

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>

=========================================================================

每天进步一点点~!

记录下前端这个一个小知识~~! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/843017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Bash 学习摘录

文章目录 1、变量和参数的介绍&#xff08;1&#xff09;变量替换$(...) &#xff08;2&#xff09;特殊的变量类型export位置参数shift 2、引用&#xff08;1&#xff09;引用变量&#xff08;2&#xff09;转义 3、条件判断&#xff08;1&#xff09;条件测试结构&#xff08…

多线程.下

目录 1.线程等待 2.join&#xff08;&#xff09;介绍 3.获取当前对象引用 4.线程的状态 5.线程安全 6.synchronized()关键字 7.synchronized关键字底层介绍 1.线程等待 对于操作系统而言&#xff0c;内部多个线程的执行是“随机调度&#xff0c;抢占式执行”的。简而言…

pico+unity3d 射线交互教程

前期配置&#xff1a;环境配置参考教程一&#xff0c;手部模型参考教程二&#xff0c;场景基于上一篇搭建。 最终效果&#xff1a;手部射线&#xff08;初始不可见&#xff09;对准 UI 显示&#xff0c;按下手柄 Trigger 键与可交互 UI&#xff08;如 Button、Toggle、Slider …

数据结构——栈(顺序结构)

一、栈的定义 栈是一种数据结构&#xff0c;它是一种只能在一端进行插入和删除操作的特殊线性表。这一端被称为栈顶&#xff0c;另一端被称为栈底。栈按照后进先出&#xff08;LIFO&#xff09;的原则进行操作&#xff08;类似与手枪装弹后射出子弹的顺序&#xff09;。在计算…

【初阶数据结构】深度解析七大常见排序|掌握底层逻辑与原理

初阶数据结构相关知识点可以通过点击以下链接进行学习一起加油&#xff01;时间与空间复杂度的深度剖析深入解析顺序表:探索底层逻辑深入解析单链表:探索底层逻辑深入解析带头双向循环链表:探索底层逻辑深入解析栈:探索底层逻辑深入解析队列:探索底层逻辑深入解析循环队列:探索…

前端调试技巧:动态高亮渲染区域

效果&#xff1a; 前端界面的渲染过程、次数&#xff0c;会通过高亮变化来显示&#xff0c;通过这种效果排除一些BUG 高亮 打开方式 F12进入后点击ESC&#xff0c;进入rendering&#xff0c;选择前三个即可&#xff08;如果没有rendering&#xff0c;点击橘色部分勾选上&…

ArrayList.subList的踩坑

需求描述&#xff1a;跳过list中的第一个元素&#xff0c;获取list中的其他元素 原始代码如下&#xff1a; List<FddxxEnterpriseVerify> companyList fddxxEnterpriseVerifyMapper.selectList(companyQueryWrapper);log.info("获取多个法大大公司数据量为&#…

深入理解Linux网络(三):TCP对象创建

深入理解Linux网络&#xff08;三&#xff09;&#xff1a;TCP对象创建 TCP对象创建inet_createsock_init_data TCP对象创建 常见的三句TCP编程&#xff1a; int main() {int sk socket(AF_INET, SOCK_STREAM, 0);connect(sk, ...)recv(sk, ...) }简单的两三⾏代码&#xff…

酷炫末世意境背景404单页HTML源码

源码介绍 酷炫末世意境背景404单页HTML源码&#xff0c;背景充满着破坏一切的意境&#xff0c;彷佛末世的到来&#xff0c;可以做网站错误页或者丢失页面&#xff0c;将下面的代码放到空白的HTML里面&#xff0c;然后上传到服务器里面&#xff0c;设置好重定向即可 效果预览 …

【面试题】Redo log和Undo log

Redo log 介绍Redo log之前我们需要了解一下&#xff0c;mysql数据操作的流程&#xff1a; 上述就是数据操作的流程图&#xff0c;可以发现sql语句并不是直接操作的磁盘而是通过操作内存&#xff0c;然后进行内存到磁盘的一个同步。这里我们必须要了解一些区域&#xff1a; 缓…

从安装Node到TypeScript到VsCode的配置教程

从安装Node到TypeScript到VsCode的配置教程 1.下载Node安装包&#xff0c; 链接 2.双击安装包&#xff0c;选择安装路径&#xff0c;如下&#xff1a; 3.一直点击下一步&#xff0c;直至安装结束即可&#xff1a; 这个时候&#xff0c;node会默认配置好环境变量&#xff0c;并且…

如何学习Hbase:糙快猛的大数据之路( 用讲故事的方式)

引言 还记得我刚踏入大数据领域的那天&#xff0c;就像一只初生的小鹿&#xff0c;对着HBase这座大山瑟瑟发抖。 但是&#xff0c;朋友们&#xff0c;让我告诉你一个秘密&#xff1a;学习就应该糙快猛&#xff01;不要追求一步到位的完美&#xff0c;在不完美中前进才是最高效…

/秋招突击——7/21——复习{堆——数组中的第K大元素}——新作{回溯——全排列、子集、电话号码的字母组合、组合总和、括号生成}

文章目录 引言复习数组中的第K大的最大元素复习实现参考实现 新作回溯模板46 全排列个人实现参考实现 子集个人实现参考实现 电话号码的字母组合复习实现 组合总和个人实现参考实现 括号生成复习实现 总结 引言 昨天的科大讯飞笔试做的稀烂&#xff0c;今天回来好好练习一下&a…

GIT命令学习 二

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…

opencv,连续拍摄多张图像求平均值减少噪点

对于照度低或者相机质量差造成的密集的随机小噪点&#xff0c;可以通过拍摄多张图像求平均值的方法来减少噪点&#xff0c;获得较为清晰的画面。 import cv2 import numpy as npclass FilterCamera:def __init__(self, cap, in_frame, num):self.cap cap # 定义的相机self.n…

Scaling Vision Transformers to 22 Billion Parameters

Scaling Vision Transformers to 22 Billion Parameters 主要贡献 Vision Transformer&#xff08;ViT&#xff09;的大规模扩展&#xff1a;尽管Transformer架构在自然语言处理&#xff08;NLP&#xff09;领域取得了巨大成功&#xff0c;但在计算机视觉&#xff08;CV&#…

NVidia 的 gpu 开源 Linux Kernel Module Driver 编译 安装 使用

见面礼&#xff0c;动态查看gpu使用情况&#xff0c;每隔2秒钟自动执行一次 nvidia-smi $ watch -n 2 nvidia-smi 1&#xff0c;找一台nv kmd列表中支持的 GPU 的电脑&#xff0c;安装ubuntu22.04 列表见 github of the kmd source code。 因为 cuda sdk 12.3支持最高到 ubu…

【JavaEE】AQS原理

本文将介绍AQS的简单原理。 首先有个整体认识&#xff0c;全称是 AbstractQueuedSynchronizer&#xff0c;是阻塞式锁和相关的同步器工具的框架。常用的ReentrantLock、Semaphore、CountDownLatch等都有实现它。 本文参考&#xff1a; 深入理解AbstractQueuedSynchronizer只需…

Haproxy服务

目录 一.haproxy介绍 1.主要特点和功能 2.haproxy 调度算法 3.haproxy 与nginx 和lvs的区别 二.安装 haproxy 服务 1. yum安装 2.第三方rpm 安装 3.编译安装haproxy 三.配置文件详解 1.官方地址配置文件官方帮助文档 2.HAProxy 的配置文件haproxy.cfg由两大部分组成&…

HTML2048小游戏

源代码在效果图后面 效果图 源代码 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>2048 Game&l…