AntD 弹框组件拖动实现方案

238 阅读1分钟

实现方案:

1. CSS3实现方案:

示例: Transform的translate实现,react代表组件库:react-draggable

import Draggable from 'react-draggable'

const DraggableModal: React.FC<
  ModalProps & {
  draggable?: boolean
}
> = ({modalRender, draggable, ...props}) => {
  return (
    <Modal
      modalRender={
        draggable !== false
          ? modal => (
            <Draggable handle=".ant-modal-header">
              {modalRender ? modalRender(modal) : modal}
            </Draggable>
          )
          : undefined
      }
      {...props}
    />
  )
}

export default DraggableModal

存在的问题: 如果内部有position:fixed布局的模块,会导致定位被降级为absolute,从而影响页面样式;

2. margin实现方案:

示例:创建dialogdrag.ts文件,引入到对应的弹出框文件中即可

let dragIng = false
let dragDom: HTMLElement | null
let dragPoint: { x: number, y: number }

document.addEventListener('mousedown', (ev: MouseEvent) => {
  let target = ev.target as HTMLElement
  if (!target.classList.contains('ant-modal-header') && !target.classList.contains('ant-modal-title') ) {
    return
  }
  dragDom = target.parentElement?.parentElement?.parentElement as HTMLElement
  if (dragDom.parentElement?.classList.contains('nodrag')) {
    dragDom = null
    return
  }
  dragIng = true
  dragPoint = {
    x: ev.clientX,
    y: ev.clientY
  }
})
document.addEventListener('mouseup', () => {
  dragIng = false
  dragDom = null
})
document.addEventListener('mousemove', (ev: MouseEvent) => {
  if (dragIng) {
    let _dragDom = dragDom as HTMLElement
    let sty = window.getComputedStyle(_dragDom, null)
    _dragDom.style.marginLeft = `${parseFloat(sty.marginLeft) + ev.clientX - dragPoint.x}px`
    _dragDom.style.marginTop = `${parseFloat(sty.marginTop) + ev.clientY - dragPoint.y}px`
    dragPoint = {
      x: ev.clientX,
      y: ev.clientY
    }
  }
})

export {}