Vue移動端實現元素拖拽


  • 最近遇到一個需求,在App內嵌的H5頁面上,有一個懸浮的客服圖標,點擊可跳轉客服頁面。最初這個客服圖標采用的是固定定位的方式。現在新的需求是,可以拖拽該圖標到屏幕任意位置,防止遮擋頁面內容。
  • 思考實現的方式就是綁定touchstarttouchmovetouchend這三個事件(PC端對應的事件分別為mousedownmousemovemouseup),動態更新元素的位置,實現元素隨手指(鼠標)移動。
  • 將邏輯處理封裝成一個mixin,方便引用。處理好滑動穿透問題,防止頁面隨元素移動而滾動。

方法封裝

/**
 * @name: draggable
 * @description: 元素拖拽
 */
const draggableMixin = {
  data () {
    return {
      // 元素位置,用於樣式綁定,動態更新位置(:style="{left: `${x}px`, top: `${y}px`}")
      elePos: {
        x: null,
        y: null
      },
      // 手指(鼠標)觸摸點[即拖拽開始的位置]距離拖拽元素左上角的距離
      diffOfTarget: {
        x: 0,
        y: 0
      }
    }
  },
  methods: {
    dragStartHandler (e) {
      let touch = e
      if (e.touches) {
        touch = e.touches[0]
      }
      this.diffOfTarget.x = touch.clientX - e.target.offsetLeft
      this.diffOfTarget.y = touch.clientY - e.target.offsetTop
      // 解決滑動穿透問題
      let scrollTop = document.scrollingElement.scrollTop
      console.log(scrollTop)
      // todo 在項目的全局樣式下,需要定義一個modal-open的樣式類
      /**
       * body.modal-open {
       *   position: fixed;
       *   width: 100%;
       *   min-height: 100%;
       * }
       */
      document.body.classList.add('modal-open')
      document.body.style.top = -scrollTop + 'px'
    },
    draggingHandler (e) {
      let touch = e
      if (e.touches) {
        touch = e.touches[0]
      }
      // 設置拖拽元素的位置
      this.elePos.x = touch.clientX - this.diffOfTarget.x
      this.elePos.y = touch.clientY - this.diffOfTarget.y
      // 限制元素不能超過屏幕
      if (this.elePos.x < 0) {
        this.elePos.x = 0
      } else if (this.elePos.x > window.screen.width) {
        this.elePos.x = window.screen.width - e.target.clientWidth
      }
      if (this.elePos.y < 0) {
        this.elePos.y = 0
      } else if (this.elePos.y > window.screen.height) {
        this.elePos.y = window.screen.height - e.target.clientHeight
      }
    },
    dragEndHandler (e) {
      document.body.classList.remove('modal-open')
    }
  }
}

export default draggableMixin


引用

<template>
  <div>
    <img
      src="../assets/img/customer-service.png"
      alt=""
      class="customer-service"
      :style="{'left': elePos.x + 'px', 'top': elePos.y + 'px' }"
      @mousedown="dragStartHandler"
      @touchstart.stop="dragStartHandler"
      @mousemove="draggingHandler"
      @touchmove.stop="draggingHandler"
      @mouseup="dragEndHandler"
      @touchend.stop="dragEndHandler"
    >
  </div>
</template>

<script>
  import draggableMixin from '@/mixins/draggable'
  export default {
    mixins: [ draggableMixin ]
  }
</script>

<style scoped>
.customer-service {
  position: fixed;
  left: 10px;
  top: 200px;
  width: 36px;
  height: 36px;
  cursor: pointer;
}
</style>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM