移动端盒子拖动效果(有效,坑已踩)(自定义指令)

思路:
1、把要拖动的元素进行相对定位,通过改变定位的px数值来实现拖动效果。
2、通过移动端手指触摸屏幕事件来计算px的值。

实现步骤:

方法一:全局封装

1、建个js文件,将方法封装成vue自定义指令
import Vue from 'vue';
// 1.参数一:指令的名称,定义时指令前面不需要写v-
// 2.参数二:是一个对象,该对象中有相关的操作函数
// 3.在调用的时候必须写v-

const drag = Vue.directive('drag', {
  // 2.每个
  // inserted表示一个元素,插入到DOM中会执行inserted函数,只触发一次,
  // 函数中第一个参数永远是el,表示绑定指令的元素,el参数是原生js对象
  // 注意:通过el.focus()是无法获取焦点的,因为只有插入DOM后才生效
  inserted: function (el) {
    // 1.开会触摸屏幕
    el.ontouchstart = function (e) {
      let disx = e.targetTouches[0].pageX - el.offsetLeft;
      let disy = e.targetTouches[0].pageY - el.offsetTop;
      let maxTop = document.body.clientHeight - el.offsetHeight
      let maxLeft = document.body.clientWidth - el.offsetWidth
      // 2.手指持续移动
      document.ontouchmove = function (e) {
        let left = e.targetTouches[0].pageX - disx
        let top = e.targetTouches[0].pageY - disy
        // 设置上下左右边界
        if (top <= 0) {
          top = 0
        } else if (top > maxTop) {
          top =  `${maxTop}px`
        }else {
          top = `${top}px`
        }
        if (left <= 0) {
          left = 0
        } else if (left > maxLeft) {
          left =  `${maxLeft}px`
        }else {
          left = `${left}px`
        }
        el.style.top = top
        el.style.left = left
      }
      // 3.手指离开屏幕
      document.ontouchend = function (e) {
        // 这里必须要清除,否则点击别的元素也会触发拖动
        document.ontouchmove = document.ontouchend = null;
      }
    }
  }
})
export default drag;
2、在要使用的vue文件内引用封装的js文件,并给要拖动的元素添加自定义指令即可
<template>
  
  <div class="goinvoice" >
    <div class="main" v-drag >div>
  div>
template>

<script>
import drag from './drag'

export default {}
script>

<style>
  .goinvoice {
    width: 100%;
    height: 100%;
    position: fixed;
    left: 0;
    top: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 100;
  }
  .main {
    width: 100px;
    height: 100px;
    background: white;
    position: absolute;
    top: 28%;
    left: 50%;
    z-index: 101;
    padding: 10px;
    border-radius: 2px;
  }
style>

方法二:组件内封装(可用于有eslint校验的项目)

1、封装
export default {
  directives: {
    drag: {
      inserted: function (el) {
        // 1.开会触摸屏幕
        el.ontouchstart = function (e) {
          let disx = e.targetTouches[0].pageX - el.offsetLeft
          let disy = e.targetTouches[0].pageY - el.offsetTop
          let maxTop = document.body.clientHeight - el.offsetHeight
          let maxLeft = document.body.clientWidth - el.offsetWidth
          // 2.手指持续移动
          document.ontouchmove = function (e) {
            let left = e.targetTouches[0].pageX - disx
            let top = e.targetTouches[0].pageY - disy
            // 设置上下左右边界
            if (top <= 0) {
              top = 0
            } else if (top > maxTop) {
              top = `${maxTop}px`
            } else {
              top = `${top}px`
            }
            if (left <= 0) {
              left = 0
            } else if (left > maxLeft) {
              left = `${maxLeft}px`
            } else {
              left = `${left}px`
            }
            el.style.top = top
            el.style.left = left
          }
          // 3.手指离开屏幕
          document.ontouchend = function (e) {
            // 这里必须要清除,否则点击别的元素也会触发拖动
            document.ontouchmove = document.ontouchend = null
          }
        }
      }
    }
  },
  
}
2、使用
<template>
  
  <div class="goinvoice" >
    <div class="main" v-drag >div>
  div>
template>

<style>
  .goinvoice {
    width: 100%;
    height: 100%;
    position: fixed;
    left: 0;
    top: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 100;
  }
  .main {
    width: 100px;
    height: 100px;
    background: white;
    position: absolute;
    top: 28%;
    left: 50%;
    z-index: 101;
    padding: 10px;
    border-radius: 2px;
  }
style>

注意:
pc端只需要把手指触摸屏幕的三个事件改成鼠标对应的三个事件,pageX 、pageY的获取方式也改一下即可e.pageX

你可能感兴趣的:(vue.js,javascript,前端)