当前位置:   article > 正文

vue实现打开多个可拖动弹窗_vue可拖拽浮动弹窗

vue可拖拽浮动弹窗

        实现可拖动这一功能的话网上教程很多,而我需要在此基础上实现点击页面打开多个可拖动弹出框

首先以下执行命令,安装vuedraggable,通过vuedraggable 实现拖动过渡动画比较好。

npm install vuedraggable --save

新建dialogDrag.js文件,文件内容如下:

  1. import Vue from 'vue'
  2. Vue.directive('dialogDrag', {
  3. bind(el) {
  4. const dialogHeaderEl = el.querySelector('.el-dialog__header')
  5. const dragDom = el.querySelector('.el-dialog')
  6. dialogHeaderEl.style.cursor = 'move'
  7. // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
  8. const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
  9. dialogHeaderEl.onmousedown = (e) => {
  10. // 鼠标按下,计算当前元素距离可视区的距离
  11. const disX = e.clientX - dialogHeaderEl.offsetLeft
  12. const disY = e.clientY - dialogHeaderEl.offsetTop
  13. const screenWidth = document.body.clientWidth // body当前宽度
  14. const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取)
  15. const dragDomWidth = dragDom.offsetWidth // 对话框宽度
  16. const dragDomheight = dragDom.offsetHeight // 对话框高度
  17. const minDragDomLeft = dragDom.offsetLeft
  18. const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
  19. const minDragDomTop = dragDom.offsetTop
  20. const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
  21. // 获取到的值带px 正则匹配替换
  22. let styL, styT
  23. // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
  24. if (sty.left.includes('%')) {
  25. styL = +document.body.clientWidth * (+sty.left.replace(/%/g, '') / 100)
  26. styT = +document.body.clientHeight * (+sty.top.replace(/%/g, '') / 100)
  27. } else {
  28. styL = +sty.left.replace(/\px/g, '')
  29. styT = +sty.top.replace(/\px/g, '')
  30. }
  31. document.onmousemove = function(e) {
  32. // 获取body的页面可视宽高
  33. // var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
  34. // var clientWidth = document.documentElement.clientWidth || document.body.clientWidth
  35. // 通过事件委托,计算移动的距离
  36. var l = e.clientX - disX
  37. var t = e.clientY - disY
  38. // 边界处理
  39. if (-l > minDragDomLeft) {
  40. l = -minDragDomLeft
  41. } else if (l > maxDragDomLeft) {
  42. l = maxDragDomLeft
  43. }
  44. if (-t > minDragDomTop) {
  45. t = -minDragDomTop
  46. } else if (t > maxDragDomTop) {
  47. t = maxDragDomTop
  48. }
  49. // 移动当前元素
  50. dragDom.style.left = `${l + styL}px`
  51. dragDom.style.top = `${t + styT}px`
  52. // 将此时的位置传出去
  53. // binding.value({x:e.pageX,y:e.pageY})
  54. }
  55. document.onmouseup = function() {
  56. document.onmousemove = null
  57. document.onmouseup = null
  58. }
  59. }
  60. }
  61. })

在页面中通过v-dialogDrag命令绑定到组件上,实现拖动效果。

  1. <el-dialog
  2. v-dialogDrag //绑定拖动效果
  3. :title="title"
  4. :lock-scroll="false"
  5. :close-on-press-escape="false"
  6. :visible.sync="dialogVisible"
  7. width="30%"
  8. :append-to-body="true" // 解决弹窗关不掉或者在弹窗框上层多出一个遮罩层的问题
  9. destroy-on-close>
  10. <el-image :src="imageUrl"></el-image>
  11. </el-dialog>

         此时已实现弹窗框的可拖动效果。

        但还未达到我的需求,接下来需要实现打开弹出框可以继续操作页面。弹出框默认是有遮罩层的,需要关闭遮罩层,同时关闭通过点击 modal 关闭 Dialog。

  1. <el-dialog
  2. v-dialogDrag //绑定拖动效果
  3. :title="title"
  4. :lock-scroll="false"
  5. :close-on-press-escape="false"
  6. :visible.sync="dialogVisible"
  7. width="30%"
  8. :append-to-body="true" // 解决弹窗关不掉或者在弹窗框上层多出一个遮罩层的问题
  9. :close-on-click-modal="false" //关闭通过点击 modal 关闭 Dialog
  10. :modal="false" // 关闭遮罩层
  11. destroy-on-close>
  12. <el-image :src="imageUrl"></el-image>
  13. </el-dialog>

接下来实现打开弹窗后可继续点击页面。

加上下边css样式即可。

  1. .el-dialog__wrapper {
  2. pointer-events: none;
  3. }
  4. .el-dialog {
  5. pointer-events:auto;
  6. }

注意:css样式一定要写对位置,否则会不生效,因为.el-dialog样式未生效,于是把.el-dialog样式写到了dialogDrag.js文化中。

最终版代码如下:

  1. import Vue from 'vue'
  2. // v-dialogDrag: 弹窗拖拽
  3. Vue.directive('dialogDrag', {
  4. bind(el) {
  5. const dialogHeaderEl = el.querySelector('.el-dialog__header')
  6. const dragDom = el.querySelector('.el-dialog')
  7. dialogHeaderEl.style.cursor = 'move'
  8. // 重点!!!!解决打开多个弹窗后,弹窗失去拖动功能
  9. // .el-dialog样式
  10. dragDom.style.pointerEvents = 'auto';
  11. // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
  12. const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
  13. dialogHeaderEl.onmousedown = (e) => {
  14. // 鼠标按下,计算当前元素距离可视区的距离
  15. const disX = e.clientX - dialogHeaderEl.offsetLeft
  16. const disY = e.clientY - dialogHeaderEl.offsetTop
  17. const screenWidth = document.body.clientWidth // body当前宽度
  18. const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取)
  19. const dragDomWidth = dragDom.offsetWidth // 对话框宽度
  20. const dragDomheight = dragDom.offsetHeight // 对话框高度
  21. const minDragDomLeft = dragDom.offsetLeft
  22. const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
  23. const minDragDomTop = dragDom.offsetTop
  24. const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
  25. // 获取到的值带px 正则匹配替换
  26. let styL, styT
  27. // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
  28. if (sty.left.includes('%')) {
  29. styL = +document.body.clientWidth * (+sty.left.replace(/%/g, '') / 100)
  30. styT = +document.body.clientHeight * (+sty.top.replace(/%/g, '') / 100)
  31. } else {
  32. styL = +sty.left.replace(/\px/g, '')
  33. styT = +sty.top.replace(/\px/g, '')
  34. }
  35. document.onmousemove = function(e) {
  36. // 获取body的页面可视宽高
  37. // var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
  38. // var clientWidth = document.documentElement.clientWidth || document.body.clientWidth
  39. // 通过事件委托,计算移动的距离
  40. var l = e.clientX - disX
  41. var t = e.clientY - disY
  42. // 边界处理
  43. if (-l > minDragDomLeft) {
  44. l = -minDragDomLeft
  45. } else if (l > maxDragDomLeft) {
  46. l = maxDragDomLeft
  47. }
  48. if (-t > minDragDomTop) {
  49. t = -minDragDomTop
  50. } else if (t > maxDragDomTop) {
  51. t = maxDragDomTop
  52. }
  53. // 移动当前元素
  54. dragDom.style.left = `${l + styL}px`
  55. dragDom.style.top = `${t + styT}px`
  56. // 将此时的位置传出去
  57. // binding.value({x:e.pageX,y:e.pageY})
  58. }
  59. document.onmouseup = function() {
  60. document.onmousemove = null
  61. document.onmouseup = null
  62. }
  63. }
  64. }
  65. })
  1. <template>
  2. <div class="dd_class_div">
  3. <el-dialog
  4. v-dialogDrag //绑定拖动效果
  5. :title="title"
  6. :lock-scroll="false"
  7. :close-on-press-escape="false"
  8. :visible.sync="dialogVisible"
  9. width="30%"
  10. :append-to-body="true" // 解决弹窗关不掉或者在弹窗框上层多出一个遮罩层的问题
  11. :close-on-click-modal="false" //关闭通过点击 modal 关闭 Dialog
  12. :modal="false" // 关闭遮罩层
  13. destroy-on-close>
  14. <el-image :src="imageUrl"></el-image>
  15. </el-dialog>
  16. </div>
  17. </template>
  18. <script>
  19. export default {
  20. name: 'draggableDialog',
  21. data() {
  22. return {
  23. dialogVisible:false,
  24. imageUrl:'',
  25. title:''
  26. }
  27. },
  28. methods: {
  29. dialogClose(){
  30. this.dialogVisible = false;
  31. }
  32. }
  33. }
  34. </script>
  35. <style scoped>
  36. .el-dialog__wrapper{
  37. pointer-events: none;
  38. }
  39. .dd_class_div {
  40. text-align: center;
  41. }
  42. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/308847
推荐阅读
相关标签
  

闽ICP备14008679号