js实现元素拖拽功能

这篇博客介绍了一个JavaScript函数,用于实现DOM元素的拖拽功能。该函数接受一个配置对象作为参数,包括可拖动元素、开始拖动、拖动中和拖动结束的回调函数等选项。它会确保元素的父元素为绝对定位,并在鼠标按下时启动拖动,鼠标移动时更新元素位置,鼠标释放时结束拖动。博客还提供了一个Vue组件的示例,展示了如何在实际项目中使用这个拖拽功能。
摘要由CSDN通过智能技术生成

让元素实现拖动指定部位或者随意部位实现整个元素拖拽功能

tips: 如果项目版本过低,不支持 ?? 或者 ?. 语法的,可以自行替换(将?删除使用&&判断,将??替换为||)

代码部分 (如果有什么地方写的不好 欢迎大家指正)
const isDom = obj => {
  if (!obj) return false
  return typeof obj === 'object' ? obj instanceof HTMLElement : false
}
/*
  * options: {
  *   dom: HTMLElement 需要移动的元素
  *   drag: HTMLElement 可拖动元素
  *   start: Function  开始拖动触发
  *   moveIng: Function  拖动中触发
  *   end: Function  拖动结束触发
  *   maxMoveDistance: Number 元素移动到最边上所暴露的最大宽度
  * }
  * */
export default function move (options = {}) {
  if (Object.keys(options).length === 0) throw new Error('请传入正确的参数')
  // drag 如果没有值,则默认dom为可以拖动元素
  const drag = options?.drag ?? options?.dom
  if (!isDom(drag)) {
    throw new Error(`${options?.drag} or ${options?.dom} is not HTMLElement`)
  }
  // NOTE:如果需要拖拽,要将父元素设置为绝对定位
  const parent = drag.parentElement ?? document.body
  // 这里只做position判断,也可以加其他判断
  const position = window.getComputedStyle(parent).getPropertyValue('position')
  if (position !== 'absolute') {
  	parent.style.position = 'absolute'
  }
  const maxMoveDistance = options?.maxMoveDistance ?? 40
  // 挂载到元素身上为了方便可以移除事件句柄
  drag.moveHandler = e => {
    if (e.which === 1) {
      // 因为有选中内容会导致拖动有bug,所以每次点击的时候把页面选中的状态取消
      document?.selection?.empty || window.getSelection?.().removeAllRanges?.()
      typeof options.start === 'function' && options.start(e)
      const startX = e.clientX
      const startY = e.clientY
      const left = options.dom.offsetLeft
      const top = options.dom.offsetTop
      // 最大可移动区域
      const maxTop = document.body.clientHeight
      const maxLeft = document.body.clientWidth
      // 移动的距离
      let distance = {x: 0, y: 0}
      document.onmousemove = ev => {
        // 移动的距离
        let x = ev.clientX - startX + left
        let y = ev.clientY - startY + top
        if ((x + maxMoveDistance) > maxLeft) {
          x = maxLeft - maxMoveDistance
        } else if (x < 0 && Math.abs((x - maxMoveDistance)) > options.dom.offsetWidth) {
          x = -(options.dom.offsetWidth - maxMoveDistance)
        }
        if ((y + maxMoveDistance) > maxTop) {
          y = maxTop - maxMoveDistance
        } else if (y <= 0) {
          y = 0
        }
        distance.x = x - left
        distance.y = y - top
        // 只要鼠标移动距离大于8才会开始移动元素,要不然没有必要
        if (Math.abs(distance.x) > 8 || Math.abs(distance.y) > 8) {
          options.dom.style.left = x + 'px'
          options.dom.style.top = y + 'px'
          typeof options.moveIng === 'function' && options.moveIng(x, y, distance)
        }
      }
      document.onmouseup = e => {
        typeof options.end === 'function' && options.end(e, distance)
        document.onmousemove = document.onmouseup = null
      }
    }
  }
  drag.addEventListener('mousedown', drag.moveHandler, false)
  return drag
}
使用
<template>
    <div class="example-container">
      <div class="content" ref="parent">
        <div class="title" ref="title"></div>
        <div class="body"></div>
      </div>
    </div>
</template>

<script>
import move from '@/utils/move/index'
export default {
  name: 'example',
  mounted () {
    const self = this
    move({
      dom: self.$refs?.parent,
      drag: self.$refs?.title
    })
  }
}
</script>
<style lang="scss" scoped>
.example-container {
  height: 100%;
  width: 100%;
    .content {
      height: 300px;
      width: 300px;
      background-color: #67C23A;
      position: absolute;
      .title {
        background-color: #409eff;
        height: 50px;
      }
    }
}
</style>

执行结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现同时兼容 PC 端和移动端的元素拖拽功能,可以使用 HTML5 新增的 drag 事件和 touch 事件。 首先,需要将元素设置为可拖拽,可以使用 draggable 属性。例如: ```html <div draggable="true">可拖拽元素</div> ``` 然后,需要监听元素的 dragstart、drag、dragend 事件或 touchstart、touchmove、touchend 事件来实现拖拽效果。 在 PC 端,可以使用 drag 事件来实现拖拽效果,例如: ```javascript var dragElement = document.getElementById('drag-element'); dragElement.addEventListener('dragstart', function(event) { // 拖拽开始时,保存拖拽元素的 ID event.dataTransfer.setData('text/plain', event.target.id); }); document.body.addEventListener('dragover', function(event) { // 阻止默认拖拽行为 event.preventDefault(); }); document.body.addEventListener('drop', function(event) { // 阻止默认拖拽行为 event.preventDefault(); // 获取拖拽元素的 ID var id = event.dataTransfer.getData('text/plain'); var dragElement = document.getElementById(id); // 将拖拽元素添加到放置区域 event.target.appendChild(dragElement); }); ``` 在移动端,可以使用 touch 事件来实现拖拽效果,例如: ```javascript var dragElement = document.getElementById('drag-element'); var startX, startY; dragElement.addEventListener('touchstart', function(event) { startX = event.touches[0].clientX; startY = event.touches[0].clientY; }); dragElement.addEventListener('touchmove', function(event) { var offsetX = event.touches[0].clientX - startX; var offsetY = event.touches[0].clientY - startY; // 移动元素 this.style.transform = 'translate(' + offsetX + 'px, ' + offsetY + 'px)'; }); dragElement.addEventListener('touchend', function(event) { // 拖拽结束时,清除 transform 样式 this.style.transform = ''; }); ``` 需要注意的是,移动端的 touch 事件可能会和浏览器默认行为冲突,需要使用 preventDefault() 方法来阻止默认行为。另外,由于移动端的屏幕尺寸多样化,需要根据具体情况来调整拖拽的逻辑和样式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值