前言
在前端开发中,弹框和实时视频播放是常见的需求。这里来简单记录一下,如何使用Vue.js和Element UI实现一个可拖动的弹框,并使用mixins混入特性,在组件中播放实时视频。同时,确保在拖拽弹框时,底层元素仍然可以操作。这里来记录一下
Cesium ~ 第 3 篇 —— Cesium上可拖拽的实时视频弹框
一、项目初始化,以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.jsexport 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.jsexport 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视频流播放https://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在项目中的使用https://blog.csdn.net/weixin_65793170/article/details/131204332
六. 小结
通过以上步骤,我们实现了一个可拖动的弹框,并在其中播放实时视频。我们使用了Vue.js和Element UI,并通过自定义混入实现了拖拽功能。同时,通过设置pointer-events
属性,确保在拖拽弹框时底层元素仍然可以操作。