Vue 拖动盒子(指令)

move.js

const move = {
  install(Vue) {
    Vue.directive('move', {
      inserted(el, binding) {
        const { x = 0, y = 0, zIndex = 100 } = binding.value || Object.create(null)
        el.style.position = 'fixed'
        el.style.top = '0'
        el.style.left = '0'
        el.style.zIndex = zIndex
        el.style.transform = `translate(${Number.parseFloat(x)}px, ${Number.parseFloat(y)}px)`
        const matrixReg = /^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/
        const matrix3dReg = /^matrix3d\((?:[-\d.]+,\s*){12}([-\d.]+),\s*([-\d.]+)(?:,\s*[-\d.]+){2}\)/
        const {
          clientWidth: windowWidth,
          clientHeight: windowHeight,
        } = document.body
        const { clientWidth: elWidth, clientHeight: elHeight } = el
        const maxX = windowWidth - elWidth
        const maxY = windowHeight - elHeight
        console.log(windowWidth, elWidth, maxX)
        let [distX, distY, handleFlag] = [0, 0, false]
        const handleMouseDown = (e) => {
          handleFlag = true
          const matrix = window.getComputedStyle(e.target, null).transform
          const matrixResult = matrix.match(matrix3dReg) || matrix.match(matrixReg)
          const [, translateX, translateY] = matrixResult
          distX = e.clientX - Number.parseFloat(translateX)
          distY = e.clientY - Number.parseFloat(translateY)
          el.style.cursor = 'move'
          window.addEventListener('mousemove', handleMouseMove)
        }
        const handleMouseUp = () => {
          handleFlag = false
          el.style.cursor = 'default'
          window.removeEventListener('mousemove', handleMouseMove)
        }
        const handleMouseMove = (e) => {
          if (!handleFlag) return false
          e.stopPropagation()
          e.preventDefault()
          const { clientX, clientY } = e
          if (clientX > windowWidth ||
            clientY > windowHeight ||
            clientX < 0 ||
            clientY < 0) {
            handleMouseUp()
            return false
          }
          let moveX = clientX - distX
          let moveY = clientY - distY
          if (moveX < 0) moveX = 0
          if (moveY < 0) moveY = 0
          if (moveX > maxX) moveX = maxX
          if (moveY > maxY) moveY = maxY
          el.style.transform = `translate(${moveX}px, ${moveY}px)`
        }
        el.addEventListener('mousedown', handleMouseDown)
        el.addEventListener('mouseup', handleMouseUp)
      }
    })
  }
}

export default move

main.js

import move from '@/components/move'
Vue.use(move)

demo.vue

<template>
  <div>
    <div class="box" v-move="coordinates"></div>
  </div>
</template>

<script>
export default {
  name: 'Move',
  data() {
    return {
      coordinates: {x: 100, y: 100, zIndex: 1000}
    }
  }
}
</script>

<style lang="scss" scoped>
.box {
  width: 200px;
  height: 200px;
  background-color: aqua;
}
</style>
posted @ 2020-12-25 11:29  demo_you  阅读(435)  评论(0编辑  收藏  举报