首页 Vue.js正文

vue实现移动端拖拽悬浮按钮

Vue.js 2022-09-01 07:09:59 1191

本文实例为大家分享了vue实现移动端拖拽悬浮按钮的具体代码,供大家参考,具体内容如下

功能介绍:

在移动端开发中,实现悬浮按钮在侧边显示,为不遮挡页面内容,允许手指拖拽换位。

大致需求:

1、按钮在页面侧边悬浮显示;
2、手指长按按钮,按钮改变样式,允许拖拽改变位置;
3、按钮移动结束,手指松开,计算距离左右两侧距离并自动移动至侧边显示;
4、移动至侧边后,按钮根据具体左右两次位置判断改变现实样式;

整体思路:

1、按钮实行position:fixed布局,在页面两侧最上层悬浮显示;
2、手指长按可使用定时器来判断,若手指松开,则关闭定时器,等待下次操作再启用;
3、跟随手指移动计算按钮与页面两侧的距离,判断手指松开时停留的位置;

简单效果展示:

具体实现:

一、position:fixed布局:

使用定位实现

<!-- 外层ul控制卡片范围 -->
<div>
  <div class="floatBtn"
    :class="[{moveBtn: longClick}, `${btnType}Btn`]">
  <span>悬浮按钮</span>
 </div>
</div>
<style lang="scss" scoped>
 @mixin notSelect{
  -moz-user-select:none; /*火狐*/
  -webkit-user-select:none; /*webkit浏览器*/
  -ms-user-select:none; /*IE10*/
  -khtml-user-select:none; /*早期浏览器*/
  user-select:none;
 }
 @mixin not-touch {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
 }
 .floatBtn {
  @include notSelect;
  @include not-touch();
  position: fixed;
  z-index: 1;
  overflow: hidden;
  width: 100px;
  left: calc(100% - 100px);
  top: calc(100% - 100px);
  color: #E0933A;
  background: #FCEBD0;
  font-size: 14px;
  height: 36px;
  line-height: 36px;
  text-align: center;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;
  &.rightBtn {
   border-radius: 20px 0 0 20px;
  }
  &.leftBtn {
   border-radius: 0 20px 20px 0;
  }
  &.moveBtn {
   border-radius: 20px;
  }
 }
</style>

二、touch事件绑定:

应用到touchstart,touchmove,touchend事件,使用定时器实现长按效果:

<div class="floatBtn"
  :class="[{moveBtn: longClick}, `${btnType}Btn`]"
  @touchstart="touchstart($event)"
  @touchmove="touchMove($event)"
  @touchend="touchEnd($event)"
>
  <span>悬浮按钮</span>
</div>
<script>
export default {
  data() {
    return {
      timeOutEvent: 0,
      longClick: 0,
      // 手指原始位置
      oldMousePos: {},
      // 元素原始位置
      oldNodePos: {},
      btnType: 'right'
    };
  },
  touchstart(ev) {
    // 定时器控制长按时间,超过500毫秒开始进行拖拽
    this.timeOutEvent = setTimeout(() => {
      this.longClick = 1;
    }, 500);
    const selectDom = ev.currentTarget;
    const { pageX, pageY } = ev.touches[0]; // 手指位置
    const { offsetLeft, offsetTop } = selectDom; // 元素位置
    // 手指原始位置
    this.oldMousePos = {
      x: pageX,
      y: pageY
    };
    // 元素原始位置
    this.oldNodePos = {
      x: offsetLeft,
      y: offsetTop
    };
    selectDom.style.left = `${offsetLeft}px`;
    selectDom.style.top = `${offsetTop}px`;
  },
  touchMove(ev) {
    // 未达到500毫秒就移动则不触发长按,清空定时器
    clearTimeout(this.timeOutEvent);
    if (this.longClick === 1) {
      const selectDom = ev.currentTarget;
      // x轴偏移量
      const lefts = this.oldMousePos.x - this.oldNodePos.x;
      // y轴偏移量
      const tops = this.oldMousePos.y - this.oldNodePos.y;
      const { pageX, pageY } = ev.touches[0]; // 手指位置
      selectDom.style.left = `${pageX - lefts}px`;
      selectDom.style.top = `${pageY - tops}px`;
    }
  },
  touchEnd(ev) {
    // 清空定时器
    clearTimeout(this.timeOutEvent);
    if (this.longClick === 1) {
      this.longClick = 0;
      const selectDom = ev.currentTarget;
      const {clientWidth, clientHeight} = document.body;
      const {offsetLeft, offsetTop} = selectDom;
      selectDom.style.left =
        (offsetLeft + 50) > (clientWidth / 2) ?
        'calc(100% - 100px)' : 0;
      if (offsetTop < 90) {
        selectDom.style.top = '90px';
      } else if (offsetTop + 36 > clientHeight) {
        selectDom.style.top = `${clientHeight - 36}px`;
      }
      this.btnType =
        (offsetLeft + 50) > (clientWidth / 2) ?
        'right' : 'left';
    }
  },
};
</script>

三、页面引入:

单个页面引入

<template>
 <floatBtn/>
</template>
<script>
import floatBtn from './floatBtn';
export default {
  components: {
    floatBtn
  },
};
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

© 编程脚本学习网