Blame view

ant-design-vue-jeecg/src/components/jeecg/JModal/ModalDragMixins.js 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import {getRefPromise} from '@/utils/util'

/** JModal 的拖拽混入 */
export default {
  data() {
    return {
      // 拖动配置
      dragSettings: {
        // 上次拖动top记录
        top: null,
        // 上次拖动left记录
        left: null,
        wrapEl: null,
        dragEl: null,
        headerEl: null,
      },
    }
  },
  watch: {
    visible() {
      if (!this.visible || !this.draggable) {
        return
      }
      this.handleDrag()
    },
    draggable() {
      if (!this.visible || !this.draggable) {
        return
      }
      this.handleDrag()
    },
  },
  methods: {
    async handleDrag() {
      let modalRef = await getRefPromise(this, 'modal')
      const dragWraps = modalRef.$el.querySelectorAll('.ant-modal-wrap')
      let wrapEl = dragWraps[0]
      if (!wrapEl) return
      this.dragSettings.wrapEl = wrapEl
      this.dragSettings.dragEl = wrapEl.querySelector('.ant-modal')
      this.dragSettings.headerEl = wrapEl.querySelector('.ant-modal-header')
      const display = getStyle(wrapEl, 'display')
      const draggable = wrapEl.getAttribute('data-drag')
      if (display !== 'none') {
        // 拖拽位置
        if (draggable === null || this.destroyOnClose) {
          this.enableDrag(wrapEl)
        }
      }
    },
    /** 启用拖拽 */
    enableDrag() {
      let {wrapEl, dragEl, headerEl} = this.dragSettings
      if (!wrapEl) return
      wrapEl.setAttribute('data-drag', this.draggable)
      if (!headerEl || !dragEl || !this.draggable) return

      // 还原上一次移动的位置
      this.resetModalPosition()

      headerEl.style.cursor = 'move'
      headerEl.onmousedown = (e) => {
        if (!e) return
        // 鼠标按下,计算当前元素距离可视区的距离
        const disX = e.clientX
        const disY = e.clientY
        const screenWidth = document.body.clientWidth // body当前宽度
        const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取)

        const dragElWidth = dragEl.offsetWidth // 对话框宽度
        const dragElHeight = dragEl.offsetHeight // 对话框高度

        const minDragElLeft = dragEl.offsetLeft

        const maxDragElLeft = screenWidth - dragEl.offsetLeft - dragElWidth
        const minDragElTop = dragEl.offsetTop
        const maxDragElTop = screenHeight - dragEl.offsetTop - dragElHeight
        // 获取到的值带px 正则匹配替换
        const domLeft = getStyle(dragEl, 'left')
        const domTop = getStyle(dragEl, 'top')
        let styL = +domLeft
        let styT = +domTop

        // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
        if (domLeft.includes('%')) {
          styL = +document.body.clientWidth * (+domLeft.replace(/%/g, '') / 100)
          styT = +document.body.clientHeight * (+domTop.replace(/%/g, '') / 100)
        } else {
          styL = +domLeft.replace(/px/g, '')
          styT = +domTop.replace(/px/g, '')
        }

        document.onmousemove = (e) => {
          // 全屏时不触发移动方法
          if (this.innerFullscreen) {
            return
          }
          // 通过事件委托,计算移动的距离
          let left = e.clientX - disX
          let top = e.clientY - disY

          // 边界处理
          if (-left > minDragElLeft) {
            left = -minDragElLeft
          } else if (left > maxDragElLeft) {
            left = maxDragElLeft
          }

          if (-top > minDragElTop) {
            top = -minDragElTop
          } else if (top > maxDragElTop) {
            top = maxDragElTop
          }

          this.setModalPosition(top + styT, left + styL)
        }

        document.onmouseup = () => {
          document.onmousemove = null
          document.onmouseup = null
        }
      }
    },

    /**
     * 移动弹窗位置
     * @param top 顶部位置
     * @param left 左侧位置
     * @param remember 是否记录位置,默认 true
     */
    setModalPosition(top, left, remember = true) {
      // 记录移动位置
      if (remember) {
        this.dragSettings.top = top
        this.dragSettings.left = left
      }
      // 移动当前元素
      this.dragSettings.dragEl.style.cssText += `;left:${left}px;top:${top}px;`
    },
    /**
     * 将弹窗移动到上次记录的位置
     */
    resetModalPosition() {
      this.setModalPosition(this.dragSettings.top, this.dragSettings.left, false)
    },

  },
}

function getStyle(dom, attr) {
  return getComputedStyle(dom)[attr]
}