vue自定义指令实现拖拽

vue指令实现元素拖拽

// ref 绑定拖拽区域范围 没有就默认body
	<div id="container" ref="container">
	// 传递参数 即 对应ref的名称
      <div id="login" v-drag="'container'">
        <div>陈年</div>
      </div>
    </div>
 // 默认相对body
 <div id="ball" v-drag></div>
// 子绝父相 定位居中 
#container {
  position: relative;
  width: 800px;
  height: 400px;
  background-color: black;
}
#login {
  width: 400px;
  height: 300px;
  background-color: #fff;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
}
#ball {
  width: 200px;
  height: 200px;
  background-color: red;
  border-radius: 50%;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  margin: auto;
}
  directives: {
    drag: {
      //  el当前元素 binding加参数 通过vnode获取vue实例
      inserted: (el, binding, vnode) => {
        // 绑定鼠标按下事件
        document.addEventListener('mousedown', (e) => {
          // 阻止事件冒泡
          e.stopPropagation()
          // 只绑定当前元素 当拖拽子元素时 不会发生移动
          if (e.target === el) {
            // 设置变量postionFlag 绑定在 父元素上 判断当前鼠标是否在要拖拽的元素内
            el.postionFlag =
              e.clientX > el.offsetLeft &&
              e.clientX < el.offsetLeft + el.clientWidth &&
              e.clientY > el.offsetTop &&
              e.clientY < el.offsetTop + el.clientHeight
            if (el.postionFlag) {
              // 由于定位居中使用的是  left: 0;top: 0;right: 0;bottom: 0;margin: auto; 此时元素 具体top和left需要重新赋值 方便后面计算
              el.style.top = el.offsetTop + 'px'
              el.style.left = el.offsetLeft + 'px'
              // 重写margin属性 不然 有问题
              el.style.margin = '0px'
              // 将鼠标当前坐标挂在到window对象上
              window.OriginMouseX = e.clientX
              window.OriginMouseY = e.clientY
            }
          }
        })
        // 鼠标移动事件
        document.addEventListener('mousemove', function (e) {
          // 判断是否出界函数
          function ifOut (left, top, relativeElement) {
            return (
              left <= relativeElement.clientWidth - el.clientWidth &&
              top <= relativeElement.clientHeight - el.clientHeight &&
              left >= 0 &&
              top >= 0
            )
          }
          // 只有鼠标在 元素内 鼠标移动才是有意义的
          if (el.postionFlag) {
            // 阻止默认事件 加上 不然有问题
            e.preventDefault()
            // 根据 ref找到需要相对的元素,没有就默认是body
            const relativeElement = vnode.context.$refs[binding.value] ? vnode.context.$refs[binding.value] : document.body
            // 确定元素新坐标
            const newLeft = e.clientX - window.OriginMouseX + el.offsetLeft
            const newTop = e.clientY - window.OriginMouseY + el.offsetTop
            if (ifOut(newLeft, newTop, relativeElement)) {
              // 重新挂载鼠标坐标
              window.OriginMouseX = e.clientX
              window.OriginMouseY = e.clientY
              // 改变元素位置
              el.style.left = newLeft + 'px'
              el.style.top = newTop + 'px'
            }
          } else {
            el.postionFlag = false
          }
        })
        document.addEventListener('mouseup', function (e) {
          // 鼠标抬起 停止移动
          el.postionFlag = false
        })
      }
    }
  }

拖拽前
拖拽后

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现小方块的效果,可以通过自定义指令实现。以下是实现步骤: 1. 在指令中绑定元素的事件监听器,包括mousedown、mousemove和mouseup事件。 2. 在mousedown事件中记录鼠标按下时的位置和元素的初始位置。 3. 在mousemove事件中计算鼠标移动的距离,并将元素的位置进行相应的调整。 4. 在mouseup事件中清除事件监听器。 下面是一个实现小方块效果的自定义指令的示例代码: ```javascript // 注册自定义指令 Vue.directive('drag', { bind: function (el, binding, vnode) { // 记录元素的初始位置 var initX, initY, startX, startY; // 鼠标按下时的事件处理函数 function mouseDownHandler(e) { initX = el.offsetLeft; initY = el.offsetTop; startX = e.clientX; startY = e.clientY; // 添加事件监听器 document.addEventListener('mousemove', mouseMoveHandler); document.addEventListener('mouseup', mouseUpHandler); } // 鼠标移动时的事件处理函数 function mouseMoveHandler(e) { var deltaX = e.clientX - startX; var deltaY = e.clientY - startY; // 计算元素的新位置 var newX = initX + deltaX; var newY = initY + deltaY; // 设置元素的新位置 el.style.left = newX + 'px'; el.style.top = newY + 'px'; } // 鼠标松开时的事件处理函数 function mouseUpHandler() { // 移除事件监听器 document.removeEventListener('mousemove', mouseMoveHandler); document.removeEventListener('mouseup', mouseUpHandler); } // 添加鼠标按下事件监听器 el.addEventListener('mousedown', mouseDownHandler); } }); ``` 使用该指令时,只需要在需要实现效果的小方块元素上添加v-drag指令即可: ```html <div v-drag class="drag-box"></div> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值