前端使用Vue和Element实现可拖动弹框效果,且不影响底层元素操作,Cesium作为底图(可拖拽的视频实时播放弹框,底层元素可以正常操作)

news2024/10/8 12:59:46

简述:在前端开发中,弹框和实时视频播放是常见的需求。这里来简单记录一下,如何使用Vue.js和Element UI实现一个可拖动的弹框,并在其中播放实时视频。同时,确保在拖拽弹框时,底层元素仍然可以操作。这里来记录一下


一、项目初始化,以Vue项目为例

首先,确保你的项目已经安装了Element UI。如果没有安装,可以使用以下命令进行安装并注册:

npm install element-ui

// 或者

cnpm install element-ui


二、创建Vue组件

这里我们创建一个包含实时视频播放功能的弹框组件。这个组件将使用Element UI的el-dialog组件,并添加拖动功能,同时添加CSS代码。确保在拖拽时底层元素可以操作。

1. 弹框组件

<template>
  <!-- 弹出框 -->
  <el-dialog
    title="实时视频播放"
    :visible.sync="dialogVisible"
    width="30%"
    :before-close="handleClose"
    :modal="false"
    :close-on-click-modal="false"
    class="cesium_dialog"
  >
    <flvVue :Url="rtsp1" v-if="dialogVisible"></flvVue>
    <span slot="footer" class="dialog-footer"> </span>
  </el-dialog>
</template>

<script>

export default {

  data() {
    return {
      dialogVisible: false, // 弹框显示状态
      rtsp1: 'rtsp://your-stream-url' // 实时视频流地址
    };
  },

  methods: {
    // 打开弹框事件
    DialogOpen(RtspUrl) {
      this.dialogVisible = true; // 显示弹框
    },
    // 关闭弹框事件
    handleClose() {
      this.dialogVisible = false; // 关闭弹框
    }
  },

};};
</script>

<style>
/* 在你的 CSS 文件或 <style> 标签中添加 */
::v-deep .el-dialog__wrapper {
  pointer-events: none !important; /* 禁用遮罩层的点击事件 */
}
::v-deep .el-dialog__wrapper .el-dialog {
  pointer-events: auto !important; /* 允许对话框内的元素交互 */
  margin-top: 20vh !important; /* 设置弹框距顶部的距离 */
}
</style>

2. 拖拽功能的实现

创建一个draggable.js文件,用于实现弹框的拖拽功能:

// src/mixins/draggable.js
export default {
  mounted() {
    // 获取对话框的头部元素
    const dialogHeaderEl = this.$el.querySelector('.el-dialog__header');
    // 获取整个对话框元素
    const dragDom = this.$el.querySelector('.el-dialog');
    // 设置头部的光标为移动样式,表示可以拖动
    dialogHeaderEl.style.cursor = 'move';

    // 函数用于获取元素的计算样式
    const getStyle = (function () {
      if (window.document.currentStyle) {
        // 对于旧版 IE,使用 currentStyle
        return (dom, attr) => dom.currentStyle[attr];
      } else {
        // 对于现代浏览器,使用 getComputedStyle
        return (dom, attr) => getComputedStyle(dom, false)[attr];
      }
    })();

    // 鼠标按下事件处理程序
    dialogHeaderEl.onmousedown = (e) => {
      // 计算鼠标点击点相对于对话框头部的偏移量
      const disX = e.clientX - dialogHeaderEl.offsetLeft;
      const disY = e.clientY - dialogHeaderEl.offsetTop;

      // 获取对话框的宽度和高度
      const dragDomWidth = dragDom.offsetWidth;
      const dragDomHeight = dragDom.offsetHeight;

      // 获取浏览器窗口的宽度和高度
      const screenWidth = document.body.clientWidth;
      const screenHeight = document.body.clientHeight;

      // 计算对话框拖动的边界
      const minDragDomLeft = dragDom.offsetLeft; // 左边界
      // 右边界
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth; 
      const minDragDomTop = dragDom.offsetTop; // 上边界
      // 下边界
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight; 

      // 获取对话框当前位置的样式(左和上),处理 px 或百分比单位
      let styL = getStyle(dragDom, 'left');
      let styT = getStyle(dragDom, 'top');

      // 处理百分比单位,将其转换为绝对像素值
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100);
        styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100);
      } else {
        // 处理 px 单位
        styL = +styL.replace(/px/g, '');
        styT = +styT.replace(/px/g, '');
      }

      // 鼠标移动事件处理程序
      document.onmousemove = function (e) {
        // 计算新的位置
        let left = e.clientX - disX;
        let top = e.clientY - disY;

        // 边界处理:防止对话框拖动超出边界
        if (-left > minDragDomLeft) {
          left = -minDragDomLeft;
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft;
        }

        if (-top > minDragDomTop) {
          top = -minDragDomTop;
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop;
        }

        // 更新对话框的位置
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
      };

      // 鼠标释放事件处理程序
      document.onmouseup = function () {
        // 解除鼠标移动和释放事件的绑定
        document.onmousemove = null;
        document.onmouseup = null;
      };

    };
  }
};};

3. 整合拖拽功能

draggable.js文件混入到你的Vue组件中,使得弹框可以实现拖动功能,同时确保拖拽时底层元素仍然可以操作。

import draggable from "@/utils/hs/draggable.js"; // 引入拖拽功能

export default {

  // 混入拖拽功能
  mixins: [draggable],

  data() {
    return {
      ......
    };
  },
  methods: {
      ......
  },

};};


三. 完整代码

1. Vue

<template>
  <!-- 弹出框 -->
  <el-dialog
    title="实时视频播放"
    :visible.sync="dialogVisible"
    width="30%"
    :before-close="handleClose"
    :modal="false"
    :close-on-click-modal="false"
    class="cesium_dialog"
  >
    <flvVue :Url="rtsp1" v-if="dialogVisible"></flvVue>
    <span slot="footer" class="dialog-footer"> </span>
  </el-dialog>
</template>

<script>
import draggable from "@/utils/hs/draggable.js"; // 引入拖拽功能

export default {

  // 混入拖拽功能
  mixins: [draggable],

  data() {
    return {
      dialogVisible: false,
      rtsp1: 'rtsp://your-stream-url'
    };
  },

  methods: {
    DialogOpen(RtspUrl) {
      this.dialogVisible = true;
    },
    handleClose() {
      this.dialogVisible = false;
    }
  },

};};
</script>

<style>
/* 在你的 CSS 文件或 <style> 标签中添加 */
::v-deep .el-dialog__wrapper {
  pointer-events: none !important; /* 禁用遮罩层的点击事件 */
}
::v-deep .el-dialog__wrapper .el-dialog {
  pointer-events: auto !important; /* 允许对话框内的元素交互 */
  margin-top: 20vh !important; /* 设置弹框距顶部的距离 */
}
</style>

2. JS

// src/mixins/draggable.js

export default {
  mounted() {
    // 获取对话框的头部元素
    const dialogHeaderEl = this.$el.querySelector('.el-dialog__header');
    // 获取整个对话框元素
    const dragDom = this.$el.querySelector('.el-dialog');
    // 设置头部的光标为移动样式,表示可以拖动
    dialogHeaderEl.style.cursor = 'move';

    // 函数用于获取元素的计算样式
    const getStyle = (function () {
      if (window.document.currentStyle) {
        // 对于旧版 IE,使用 currentStyle
        return (dom, attr) => dom.currentStyle[attr];
      } else {
        // 对于现代浏览器,使用 getComputedStyle
        return (dom, attr) => getComputedStyle(dom, false)[attr];
      }
    })();

    // 鼠标按下事件处理程序
    dialogHeaderEl.onmousedown = (e) => {
      // 计算鼠标点击点相对于对话框头部的偏移量
      const disX = e.clientX - dialogHeaderEl.offsetLeft;
      const disY = e.clientY - dialogHeaderEl.offsetTop;

      // 获取对话框的宽度和高度
      const dragDomWidth = dragDom.offsetWidth;
      const dragDomHeight = dragDom.offsetHeight;

      // 获取浏览器窗口的宽度和高度
      const screenWidth = document.body.clientWidth;
      const screenHeight = document.body.clientHeight;

      // 计算对话框拖动的边界
      const minDragDomLeft = dragDom.offsetLeft; // 左边界
      // 右边界
      const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
      const minDragDomTop = dragDom.offsetTop; // 上边界
      // 下边界
      const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight; 
      // 获取对话框当前位置的样式(左和上),处理 px 或百分比单位
      let styL = getStyle(dragDom, 'left');
      let styT = getStyle(dragDom, 'top');

      // 处理百分比单位,将其转换为绝对像素值
      if (styL.includes('%')) {
        styL = +document.body.clientWidth * (+styL.replace(/%/g, '') / 100);
        styT = +document.body.clientHeight * (+styT.replace(/%/g, '') / 100);
      } else {
        // 处理 px 单位
        styL = +styL.replace(/px/g, '');
        styT = +styT.replace(/px/g, '');
      }

      // 鼠标移动事件处理程序
      document.onmousemove = function (e) {
        // 计算新的位置
        let left = e.clientX - disX;
        let top = e.clientY - disY;

        // 边界处理:防止对话框拖动超出边界
        if (-left > minDragDomLeft) {
          left = -minDragDomLeft;
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft;
        }

        if (-top > minDragDomTop) {
          top = -minDragDomTop;
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop;
        }

        // 更新对话框的位置
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
      };

      // 鼠标释放事件处理程序
      document.onmouseup = function () {
        // 解除鼠标移动和释放事件的绑定
        document.onmousemove = null;
        document.onmouseup = null;
      };
    };
  }
};};


四. 请求RTSP视频流播放,请看

前端请求RTSP视频流播放icon-default.png?t=N7T8https://blog.csdn.net/weixin_65793170/article/details/140049511?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22140049511%22%2C%22source%22%3A%22weixin_65793170%22%7D


五. Cesium在项目中使用的详细介绍,请看以下

Cesium在项目中的使用icon-default.png?t=N7T8https://blog.csdn.net/weixin_65793170/article/details/131204332


六. 小结

通过以上步骤,我们实现了一个可拖动的弹框,并在其中播放实时视频。我们使用了Vue.js和Element UI,并通过自定义混入实现了拖拽功能。同时,通过设置pointer-events属性,确保在拖拽弹框时底层元素仍然可以操作。

创作不易,感觉有用,就一键三连😄点赞、收藏加关注,感谢(●'◡'●)

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

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

相关文章

常用知识碎片 分页组件的使用(arco-design组件库)

目录 分页组件使用 API 组件代码示例 使用思路&#xff1a; 前端示例代码 html script 后端示例代码 Controller Impl xml 总结 分页组件使用 使用Arco Design之前需要配置好搭建前端环境可以看我另外一篇文章&#xff1a; 手把手教你 创建Vue项目并引入Arco Desi…

【JavaWeb程序设计】Servlet(二)

目录 一、改进上一篇博客Servlet&#xff08;一&#xff09;的第一题 1. 运行截图 2. 建表 3. 实体类 4. JSP页面 4.1 login.jsp 4.2 loginSuccess.jsp 4.3 loginFail.jsp 5. mybatis-config.xml 6. 工具类&#xff1a;创建SqlSessionFactory实例&#xff0c;进行 My…

十八.升职加薪系列-JVM垃圾回收器-开天辟地的ZGC

前言 随着Java的发展&#xff0c;JVM的GC垃圾回收器也在跟着升级&#xff0c;从早起的单线程垃圾回收器Serial&#xff0c;到多线程的垃圾回收器Parallel Scavenge&#xff0c;再到并发垃圾回收器CMS,G1等。它们在某些对延迟要求比较高的系统来说都有些力不从心,比如&#xff…

物联网系统中市电电量计量方案(一)

为什么要进行电量计量&#xff1f; 节约资源&#xff1a;电量计量可以帮助人们控制用电量&#xff0c;从而达到节约资源的目的。在当前严峻的资源供应形势下&#xff0c;节约能源是我们应该重视的问题。合理计费&#xff1a;电表可以帮助公共事业单位进行合理计费&#xff0c;…

R包:‘ggcharts好看线图包‘

介绍 ggcharts提供了一个高级{ggplot2}接口&#xff0c;用于创建通用图表。它的目标既简单又雄心勃勃:让您更快地从数据可视化的想法到实际的绘图。所以如何?通过处理大量的数据预处理&#xff0c;为您模糊{ggplot2}细节和绘图样式。生成的图是ggplot对象&#xff0c;可以使用…

物联网系统中市电电量计量方案(二)

上文我们主要介绍了电量计量中最重要的组成部分——电量计量芯片&#xff08;如果没有阅读该文章的&#xff0c;可以点击这里&#xff09;。本文会再为大家介绍电量计量的另外一个组成部分——电流互感器。 电流互感器的定义 电流互感器是一种可将一次侧大电流转换为二次侧小电…

Sentinel-1 Level 1数据处理的详细算法定义(三)

《Sentinel-1 Level 1数据处理的详细算法定义》文档定义和描述了Sentinel-1实现的Level 1处理算法和方程&#xff0c;以便生成Level 1产品。这些算法适用于Sentinel-1的Stripmap、Interferometric Wide-swath (IW)、Extra-wide-swath (EW)和Wave模式。 今天介绍的内容如下&…

室内精准定位哪个产品抗干扰能力强?可以用于哪些方面?

室内精准定位产品其实有很多&#xff0c;其实它是安装在室内接收型号的一个基站&#xff0c;并且范围有一定的限制&#xff0c;而被定位的人员需要携带定位产品&#xff0c;那么通过室内基站收集到的信息&#xff0c;将会通过专业的系统处理后呈现在相应的设备上&#xff0c;比…

Linux下常见压缩文件tar.xz、tar.bz2、tar.gz的区别和详解

文章目录 tar.xz tar.bz2 tar.gz 的区别三种文件的解压方式tar.xz的解压三种压缩文件的创建方式 tar.xz tar.bz2 tar.gz 的区别 这三个文件扩展名都表示压缩后的档案文件&#xff0c;但它们使用不同的压缩算法。 tar.xz: tar 代表 Tape Archive&#xff0c;它是一种将多个文件…

f_mkfs格式化最小分区数是191

使用fatfs的f_mkfs最小分区数是191原因&#xff1a; 在挂载ram_disk时参考的文章有提到&#xff1a; “然后是GET_SECTOR_COUNT 用于f_mkfs格式化时获取可用的sector的数量&#xff0c;32bit-LBA的情况下至少为191” 自己也实际试过确实要不少于191&#xff0c;网上也没找到相…

WMS系统的模块构成

WMS系统的模块构成通常包括以下几个主要部分&#xff1a; ———————————————————————————————— 1、库存管理&#xff1a; 主要负责管理仓库内的库存信息&#xff0c;包括库存记录、库存调整、库存盘点等功能。 2、入库管理&#xff1a; 负责处…

samba共享windows和ubuntu的文件

通过Samba服务器实现Windows与Ubuntu之间的文件共享是一个常见的需求&#xff0c;下面是实现这一目标的详细步骤&#xff1a; 一、Ubuntu开启Samba服务器 安装Samba&#xff1a; 打开终端&#xff0c;使用以下命令安装Samba服务&#xff1a; sudo apt update sudo apt install…

html js 3d z轴移动 实现星空

用chatgpt还有kimi 让实现动画效果的星空,都太垃圾了 不是y轴移动,就是x轴移动, 我要z轴移动,他们就是搞不出来, ai写代码还有很长的路。 <!DOCTYPE html> <meta charset="utf-8" /> <head> <title>ai相关博客</title> </h…

同享人力资源管理系统-TXEHR V15 DownloadTemplate 文件读取漏洞复现

0x01 产品简介 同享人力资源管理系统(TXEHR V15)是一款专为现代企业设计的人力资源管理软件解决方案,旨在通过先进的信息化手段提升企业人力资源管理的效率与水平。该系统集成了组织人事、考勤管理、薪资核算、招聘配置、培训发展、绩效管理等核心模块,并提供了灵活的配置…

UNIAPP_ReferenceError: TextEncoder is not defined 解决

错误信息 1、安装text-decoding npm install text-decoding2、main.js import { TextEncoder, TextDecoder } from text-decoding global.TextEncoder TextEncoder global.TextDecoder TextDecoder

专注于国产FPGA芯片研发的异格技术Pre-A+轮融资,博将控股再次投资

近日&#xff0c;苏州异格技术有限公司&#xff08;以下简称“异格技术”&#xff09;宣布成功完成数亿元的Pre-A轮融资&#xff0c;由博将控股在参与Pre-A轮投资后&#xff0c;持续投资。这标志着继2022年获得经纬中国、红点中国、红杉中国等机构数亿元天使轮融资后&#xff0…

C 语言中如何进行函数指针的回调?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; &#x1f4d9;C 语言百万年薪修炼课程 【https://dwz.mosong.cc/cyyjc】通俗易懂&#xff0c;深入浅出&#xff0c;匠心打磨&#xff0c;死磕细节&#xff0c;6年迭代&…

系统架构设计师 - 数学与经济管理

数学与经济管理 数学与经济管理&#xff08;1 - 2分&#xff09;图论应用最小生成树最短路径网络与最大流量 ★ 运筹方法关键路径法 ★ ★ ★线性规划 ★动态规划 ★ ★ ★排队论预测与决策 ★预测 - 博弈论决策 数学建模 ★ ★ 大家好呀&#xff01;我是小笙&#xff0c;本章我…

Java版Flink使用指南——将消息写入到RabbitMQ的队列中

大纲 新建工程新增依赖 编码自动产生数据写入RabbitMQ 测试工程代码 在 《Java版Flink使用指南——从RabbitMQ中队列中接入消息流》一文中&#xff0c;我们介绍了如何使用Java在Flink中读取RabbitMQ中的数据&#xff0c;并将其写入日志中。本文将通过代码产生一些数据&#xf…

OTA与OTA升级

目录 一、OTA简介 二、OTA升级 三、操作方式 一、OTA简介 在嵌入式领域当中&#xff0c;OTA&#xff08;Over-The-Air&#xff09;指的是通过无线通信技术对嵌入式设备的软件进行远程更新和管理。这种技术广泛应用于物联网设备、智能家电、汽车电子、智能手机等领域。通过OTA…