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

news2024/9/22 7:30:28

目录

一、需求描述

二、实现效果

三、完整代码

四、实现过程

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.coloradmin.cn/o/1921681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【离线查询 堆 优先队列】1383. 最大的团队表现值

本文涉及知识点 离线查询 堆 优先队列 算法与数据结构汇总 LeetCode1383. 最大的团队表现值 给定两个整数 n 和 k&#xff0c;以及两个长度为 n 的整数数组 speed 和 efficiency。现有 n 名工程师&#xff0c;编号从 1 到 n。其中 speed[i] 和 efficiency[i] 分别代表第 i 位…

开源项目的认识理解

目录 开源项目有哪些机遇与挑战&#xff1f; 1.开源项目的发展趋势 2.开源的经验分享&#xff08;向大佬请教与上网查询&#xff09; 3.开源项目的挑战 开源项目有哪些机遇与挑战&#xff1f; 1.开源项目的发展趋势 1. 持续增长与普及 - 开源项目将继续增长&#xff0c…

软件测试——AI快速入门

工作职责&#xff1a; 1.负责产品系统测试&#xff0c;包括功能测试、性能测试、稳定性测试、用户场景测试、可靠性测试等。 2.负责测试相关文档的编写&#xff0c;包括测试计划、测试用例、测试报告等。 3.负责自动化测试框架、用例的维护。 岗位要求&#xff1a; 1.熟练…

编程范式之并发编程

目录 前言1. 并发编程的定义2. 并发编程的特点2.1 任务交替执行2.2 状态共享与同步2.3 并行执行 3. 并发编程的适用场景3.1 高性能计算3.2 I/O 密集型应用3.3 实时系统 4. 并发编程的优点4.1 提高资源利用率4.2 缩短响应时间4.3 提高系统吞吐量 5. 并发编程的缺点5.1 编程复杂性…

MP4怎么转为MP3?超多人都在用的四种转换方法!

MP4怎么转为MP3&#xff1f;MP4&#xff0c;这一风靡全球的多媒体容器格式&#xff0c;无疑是数字时代的一枚璀璨明珠&#xff0c;深深烙印在每个人的数字生活之中&#xff0c;那么&#xff0c;它究竟是如何在众多格式中脱颖而出&#xff0c;赢得如此广泛认可的呢&#xff1f;首…

【Redis】初识 Redis

文章目录 1 什么是 Redis2 Redis 的特点2.1 速度快2.2 可编程性2.3 可拓展性2.4 持久化2.5 主从复制2.5 高可用和分布式2.6 客户端语言多 3 Redis 使用场景3.1 实时数据存储3.2 缓存和 Session 存储3.3 消息队列 4 Redis 重大版本5 CentOS7 安装 Redis5 1 什么是 Redis Redis …

【typedb】例子:药物发现 1: 模式导入

typedb-examples/drug-discovery/ Drug discovery监听0.0.0.0:1729 但这么连接肯定不行: localhost:1729 可以: 一直无法点击schema图标:先创建一个数据库 选中数据库: 选中后就可以了:

分布式存储快速入门HDFS

分布式存储快速入门 文章目录 分布式存储快速入门一、概要介绍1.1 什么是分布式存储1.2 分布式存储的重要性和应用场景 二、HDFS基础2.1 HDFS的起源和发展2.2 HDFS的架构2.3 HDFS的基本概念2.4 HDFS的特性2.5 HDFS的版权 三、HDFS安装与配置3.1 环境准备3.2 安装Hadoop和配置HD…

你也想做一个Element-ui吧!!!——Blueの前端路(一)

目录 前言&#xff1a; 父子组件 button组件 使用vue脚手架初始化一个项目 如何封装&#xff0c;注册和使用一个组件 main.js中将组件设置为全局 使用 此组件我们所需实现的内容 type 父组件组件传递type属性 子组件接收负组件传递的数据 通过绑定类名的方法动态控制…

python如何结束程序运行

方法1&#xff1a;采用sys.exit(0)&#xff0c;正常终止程序&#xff0c;从图中可以看到&#xff0c;程序终止后shell运行不受影响。 方法2&#xff1a;采用os._exit(0)关闭整个shell&#xff0c;从图中看到&#xff0c;调用sys._exit(0)后整个shell都重启了&#xff08;RESTAR…

关键路径-matlab

路径上边的数目称为路径长度 图的基本知识 求最短路径&#xff08;Dijkstra算法&#xff09; 2. 待继续尝试 ①Dijkstra ②floyd_all.m 一 二 ③ LeetCode [329. 矩阵中的最长递增路径]

OpenCV solvePnP位姿估计

目录 一、概述 二、实现代码 2.1solvePnP函数 2.1.1输入参数 2.1.2输出参数 2.2完整代码 三、实现效果 3.1标定板位姿 3.2标定板到相机的变换矩阵 一、概述 完成相机标定后&#xff0c;可以通过检测标定板在图像中的位置来计算标定板在相机坐标系下的位姿&#xff08;…

Python基础知识——(004)

文章目录 P16——15. 布尔类型 P17——16. 类型转换函数 P18——17. eval函数 P19——18. 算数运算符 P20——19. 赋值运算符 P16——15. 布尔类型 布尔类型 用来表示 “真” 值或 “假” 值的数据类型在Python中使用标识符 True 或 False 表示布尔类型的值True表示整数1&…

python的集合

定义 集合&#xff08;是一个无序的、不包含重复元素的集合。集合对象支持数学上的标准集合操作&#xff0c;如并集、交集、差集等。&#xff09; 创建集合 添加元素 删除元素 遍历 其他 union() 或 |&#xff1a;返回两个集合的 并集intersection() 或 &&#xff1a;返回…

关于共享盘(文件夹)

1、创建共享文件夹或共享盘 对应文件或盘-》右键-》属性-》共享或高级共享 2、设置权限来针对不同的用户进行访问 2.1 关于用户的添加 电脑->计算机管理->添加用户和组 2.2 本地用户 在属性的安全之中&#xff0c;可针对不同的用户和组进行权限设置&#xff0c;例如某…

MYSQL--第七次作业

MYSQL–第七次作业 在product表上创建三个触发器。每次激活触发器后&#xff0c;都会更新operate表。product表和表的内容如下 Product表内容 字段名 字段描述 数据类型 主键 外键 非空 唯一 自增 Id 产品编号 Int(10) 是 否 是 是 否 Name …

iPad锁屏密码忘记怎么办?有什么方法可以解锁?

当我们在日常使用iPad时&#xff0c;偶尔可能会遇到忘记锁屏密码的尴尬情况。这时&#xff0c;不必过于担心&#xff0c;因为有多种方法可以帮助您解锁iPad。接下来&#xff0c;小编将为您详细介绍这些解决方案。 一、使用iCloud的“查找我的iPhone”功能 如果你曾经启用了“查…

Nginx:关于实现跨域代理

运维专题 Nginx&#xff1a;关于实现跨域代理 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.ne…

openWrt(3) - ubus (下)

参考自: [OpenWrt Wiki] ubus&#xff08;OpenWrt微总线架构&#xff09; --- [OpenWrt Wiki] ubus (OpenWrt micro bus architecture) ubus补充 查看注册到 ubusd 的所有服务的所有方法&#xff1a; ubus -v list system 调用远程方法并接收回复。回复可以是简单的整数返回…

超声波清洗机哪个牌子好?耐用的超声波眼镜清洗机推荐

超声波清洗机大家也一定不陌生了&#xff0c;提起超声波清洗机啊&#xff0c;大家对他的印象一定是清洗眼镜&#xff0c;这话没毛病&#xff0c;但是&#xff0c;这仅仅只是清洗机的基本功&#xff0c;清洗机的功能远远比咱们想象中的强大&#xff0c;但是目前市面上的小型超声…