vue3编写的自定义的拉伸panel指令

这里要注意三个问题:
1. 组件的元素上要加入, pointer-events: all,不然会选不中当前的拖拽组件
2. 父组件要设置 position: 'relative',
3. 如果用了 vueuse库写拖拽功modal的功能可以把 这个指令放在modalRender的插槽处类似:

复制代码
 modalRender: ({ originVNode }) => {
              return (
                <div
                  id="modal-render"
                  class="modal-render"
                  style={{ ...transformStyle.value }}
                  v-el-drawer-drag-width
                >
                  {originVNode}
                </div>
              )
            },
复制代码

这样,这里我用的是tsx的vue写法

后续插件完整代码如下:

复制代码
import { App, onBeforeUnmount } from 'vue'
/**
 * el-drawer 拖拽指令,处理DIV宽度拖拽
 */
export default {
  install(app: App) {
    app.directive('el-drawer-drag-width', {
      mounted(el) {
        const drawerEle = el
        // 创建触发拖拽的元素
        const dragItem = document.createElement('div')
        dragItem.style.cssText =
          'height: 100vh;width: 5px;cursor: col-resize;position: absolute;right: 0px;z-index: 9999;top: 0;pointer-events: all;'
        drawerEle.append(dragItem)
        // dragItem.style.height = drawerEle.clientHeight + 'px'

        const updateDrawerHeight = () => {
          dragItem.style.height = drawerEle.clientHeight + 'px' // 更新拖拽元素的高度
        }
        updateDrawerHeight()

        // 添加窗口大小变化的监听器
        window.addEventListener('resize', updateDrawerHeight)

        const onMouseMove = (moveEvent: MouseEvent) => {
          const drawerEleRect = drawerEle.getBoundingClientRect()
          const drawerEleRectWidth = drawerEleRect.width
          // 计算新的宽度
          const dragItemRect = dragItem.getBoundingClientRect() // 获取 dragItem 的位置
          const newWidth = drawerEleRectWidth + moveEvent.pageX - dragItemRect.x // 使用 dragItem 的右边界计算新的宽度
          const width30 = document.body.clientWidth * 0.2
          const width80 = document.body.clientWidth * 0.8

          // 宽度不能大于浏览器宽度 80%,不能小于宽度的 20%
          drawerEle.style.width = `${Math.min(
            Math.max(newWidth, width30),
            width80
          )}px`
        }

        const onMouseUp = () => {
          drawerEle.style.userSelect = 'initial'
          document.removeEventListener('mousemove', onMouseMove)
          document.removeEventListener('mouseup', onMouseUp)
          dragItem.style.pointerEvents = 'all' // 确保 dragItem 可点击
        }

        // 在 当前使用指令的dom 上监听 mousedown 事件
        drawerEle.addEventListener('mousedown', (downEvent) => {
          const target = downEvent.target as HTMLElement
          if (target === dragItem) {
            // 确保是 dragItem 被点击
            drawerEle.style.userSelect = 'none'
            document.addEventListener('mousemove', onMouseMove)
            document.addEventListener('mouseup', onMouseUp)
          }
        })

        // 在组件卸载时移除监听器
        onBeforeUnmount(() => {
          window.removeEventListener('resize', updateDrawerHeight)
        })
      },
    })
  },
}
复制代码

 

posted @   洛晨随风  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示