关于前端:Vue-自定义指定拖拽

35次阅读

共计 2249 个字符,预计需要花费 6 分钟才能阅读完成。

前言

被推拽元素,与其父元素,须放弃子绝父相,或子绝父绝。

案例

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0 , maximum-scale=1, minimum-scale=1, user-scalable=no" />
    <title>Vue 自定义指令:拖拽 </title>
    <link rel="shortcut icon" href="https://gw.alipayobjects.com/mdn/prod_resou/afts/img/A*CUIoT4xopNYAAAAAAAAAAABkARQnAQ" type="image/x-icon" />
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.13/vue.js"></script>
    <style>
      * {
        margin: 0;
        padding: 0;
        overflow: hidden;
        box-sizing: border-box;
      }
      #app {
        width: 100vw;
        height: 100vh;
        overflow: hidden;
      }
      .box {
        display: flex;
        justify-content: center;
        align-items: center;
        position: absolute;
        width: 100px;
        height: 100px;
        border-radius: 10px;
        color: #fff;
        background-color: cadetblue;
        font-size: 60px;
        font-weight: bold;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box" v-drag>1</div>
      <div class="box" v-drag>2</div>
      <div class="box" v-drag>3</div>
      <div class="box" v-drag>4</div>
      <div class="box" v-drag>5</div>
      <div class="box" v-drag>6</div>
      <div class="box" v-drag>7</div>
      <div class="box" v-drag>8</div>
      <div class="box" v-drag>9</div>
    </div>

    <script>
      // 设置为 false 以阻止 Vue 在启动时生成生产提醒
      Vue.config.productionTip = false

      // new 一个 Vue 实例,并挂载到 #app 上
      new Vue({
        el: '#app',
        data() {return {}
        },
        directives: {
          // 对象写法,利用 inserted 钩子确保元素曾经被插入 DOM 时才执行
          drag: {inserted(el) {el.onmousedown = (event) => {
                const parentEl = el.parentElement
                // 避免选中拖拽导致登程浏览器的搜寻事件
                event.preventDefault()
                // 获取鼠标与拖拽盒子的偏移量(确保鼠标始终在点击盒子时的地位)const boxX = event.clientX - el.offsetLeft
                const boxY = event.clientY - el.offsetTop
                // 计算极限偏移量
                const maxX = parentEl.offsetWidth - el.offsetWidth
                const maxY = parentEl.offsetHeight - el.offsetHeight
                // 获取拖拽元素的初始定位层级
                const el_style = window.getComputedStyle(el, null)
                const origin_zIndex = el_style.zIndex
                const origin_cursor = el_style.cursor
                el.style.zIndex = '9999'
                el.style.cursor = 'move'

                document.onmousemove = (event) => {
                  // 获取鼠标以后的地位
                  const mouseX = event.clientX
                  const mouseY = event.clientY
                  // 计算被拖拽盒子的偏移量
                  let moveX = mouseX - boxX
                  let moveY = mouseY - boxY
                  // 限度盒子的推拽范畴
                  moveX < 0 && (moveX = 0)
                  moveY < 0 && (moveY = 0)
                  moveX > maxX && (moveX = maxX)
                  moveY > maxY && (moveY = maxY)

                  // 赋予待拖拽的盒子新地位
                  el.style.left = moveX + 'px'
                  el.style.top = moveY + 'px'
                }

                document.onmouseup = (event) => {
                  // 还原初始层级 && 鼠标款式
                  el.style.zIndex = origin_zIndex
                  el.style.cursor = origin_cursor
                  document.onmousemove = null
                  document.onmouseup = null
                }
              }
            },
          },
        },
      })
    </script>
  </body>
</html>

正文完
 0