简述:在前端开发中,弹框和实时视频播放是常见的需求。这里来简单记录一下,如何使用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;
};
};
}
};};
四、小结
通过以上步骤,我们实现了一个可拖动的弹框,并在其中播放实时视频。我们使用了Vue.js和Element UI,并通过自定义混入实现了拖拽功能。同时,通过设置pointer-events
属性,确保在拖拽弹框时底层元素仍然可以操作。