vue实现带自动吸附功能的悬浮球

本文实例为大家分享了vue实现带自动吸附功能的悬浮球,供大家参考,具体内容如下

封装的组件代码,可以引到页面直接使用

<template>
  <div
    ref="floatDrag"
    class="float-position"
    :style="{ left: left + 'px', top: top + 'px', zIndex: zIndex }"
    @touchmove.prevent
    @mousemove.prevent
    @mousedown="mouseDown"
    @mouseup="mouseUp"
  >
    <svg
      t="1630029318602"
      class="icon"
      viewBox="0 0 1024 1024"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
      p-id="1244"
      width="200"
      height="200"
    >
      <path
        d="M554.376075 850.102995l0.208185 87.874926 170.711774-0.14573v85.355887l-209.038649 0.187367c-1.39484 0.124911-2.727225 0.41637-4.163702 0.41637s-2.706406-0.291459-4.163702-0.41637l-208.997011 0.187366v-85.230975l170.33704-0.14573-0.208185-88.041474A383.643483 383.643483 0 0 1 128.200378 469.061825h84.772969a298.37087 298.37087 0 0 0 294.769268 297.704678c1.290748-0.124911 2.539858-0.395552 3.872243-0.395551s2.498221 0.270641 3.76815 0.374733a298.350052 298.350052 0 0 0 294.60272-297.704678h85.751438a383.664302 383.664302 0 0 1-341.361091 381.061988z m-42.240755-168.047005A213.160713 213.160713 0 0 1 298.93297 468.936914h0.458007l-0.374733-255.65129a213.160713 213.160713 0 0 1 426.300608-1.936121c0 0.374733 0.124911 0.728648 0.124911 1.124199l0.374733 256.463212a42.782036 42.782036 0 0 1-0.791103 7.890215 213.035802 213.035802 0 0 1-212.890073 205.228861z m128.32529-213.223168l-0.374734-255.65129h-0.333096a127.721552 127.721552 0 0 0-255.422286 0h-0.166548l0.374733 255.65129v1.061744a127.659097 127.659097 0 0 0 255.318194-0.957652h0.624555a0.895196 0.895196 0 0 0-0.124911-0.104092z m-129.366215-42.532214h2.081851H510.990302z"
        fill="#fff"
        p-id="1245"
      ></path>
    </svg>
  </div>
</template>

<script>
export default {
  name: "DragBall",
  props: {
    distanceRight: {
      type: Number,
      default: 0
    },
    distanceBottom: {
      type: Number,
      default: 100
    },
    isScrollHidden: {
      type: Boolean,
      default: false
    },
    isCanDraggable: {
      type: Boolean,
      default: true
    },
    zIndex: {
      type: Number,
      default: 50
    },
    value: {
      type: String,
      default: "悬浮球!"
    }
  },

  //data 域
  data() {
    return {
      clientWidth: null,
      clientHeight: null,
      left: 0,
      top: 0,
      timer: null,
      currentTop: 0,
      mousedownX: 0,
      mousedownY: 0
    };
  },
  created() {
    this.clientWidth = document.documentElement.clientWidth;
    this.clientHeight = document.documentElement.clientHeight;
  },
  mounted() {
    this.isCanDraggable &&
      this.$nextTick(() => {
        this.floatDrag = this.$refs.floatDrag;
        // 获取元素位置属性
        this.floatDragDom = this.floatDrag.getBoundingClientRect();
        // 设置初始位置
        this.left =
          this.clientWidth - this.floatDragDom.width - this.distanceRight;
        this.top =
          this.clientHeight - this.floatDragDom.height - this.distanceBottom;
        this.initDraggable();
      });
    this.isScrollHidden && window.addEventListener("scroll", this.handleScroll);
    window.addEventListener("resize", this.handleResize);
  },
  methods: {
    /**
     * 设置滚动监听
     * 设置滚动时隐藏悬浮按钮,停止时显示
     */
    handleScroll() {
      this.timer && clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.handleScrollEnd();
      }, 200);
      this.currentTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (this.left > this.clientWidth / 2) {
        // 判断元素位置再左侧还是右侧
        this.left = this.clientWidth + this.floatDragDom.width;
      } else {
        this.left = -this.floatDragDom.width;
      }
    },
    /**
     * 滚动结束
     */
    handleScrollEnd() {
      let scrollTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (scrollTop === this.currentTop) {
        console.log(this.left);
        if (this.left > this.clientWidth / 2) {
          // 判断元素位置再左侧还是右侧
          this.left = this.clientWidth - this.floatDragDom.width;
        } else {
          this.left = 0;
        }
        clearTimeout(this.timer);
      }
    },
    /**
     * 窗口resize监听
     */
    handleResize() {
      this.clientWidth = document.documentElement.clientWidth;
      this.clientHeight = document.documentElement.clientHeight;
      this.checkDraggablePosition();
    },
    /**
     * 初始化draggable
     */
    initDraggable() {
      this.floatDrag.addEventListener("touchstart", this.toucheStart);
      this.floatDrag.addEventListener("touchmove", e => this.touchMove(e));
      this.floatDrag.addEventListener("touchend", this.touchEnd);
    },
    mouseDown(e) {
      const event = e || window.event;
      this.mousedownX = event.screenX;
      this.mousedownY = event.screenY;
      const that = this;
      let floatDragWidth = this.floatDragDom.width / 2;
      let floatDragHeight = this.floatDragDom.height / 2;
      if (event.preventDefault) {
        event.preventDefault();
      }
      this.canClick = false;
      this.floatDrag.style.transition = "none";
      document.onmousemove = function(e) {
        var event = e || window.event;
        that.left = event.clientX - floatDragWidth;
        that.top = event.clientY - floatDragHeight;
        if (that.left < 0) that.left = 0;
        if (that.top < 0) that.top = 0;
        if (that.left >= that.clientWidth - floatDragWidth * 2) {
          that.left = that.clientWidth - floatDragWidth * 2;
        }
        if (that.top >= that.clientHeight - floatDragHeight * 2) {
          that.top = that.clientHeight - floatDragHeight * 2;
        }
      };
    },
    mouseUp(e) {
      const event = e || window.event;
      //判断只是单纯的点击,没有拖拽
      if (
        this.mousedownY == event.screenY &&
        this.mousedownX == event.screenX
      ) {
        this.$emit("handlepaly");
      }
      document.onmousemove = null;
      this.checkDraggablePosition();
      this.floatDrag.style.transition = "all 0.3s";
    },
    toucheStart() {
      this.canClick = false;
      this.floatDrag.style.transition = "none";
    },
    touchMove(e) {
      this.canClick = true;
      if (e.targetTouches.length === 1) {
        // 单指拖动
        let touch = event.targetTouches[0];
        this.left = touch.clientX - this.floatDragDom.width / 2;
        this.top = touch.clientY - this.floatDragDom.height / 2;
      }
    },
    touchEnd() {
      if (!this.canClick) return; // 解决点击事件和touch事件冲突的问题
      this.floatDrag.style.transition = "all 0.3s";
      this.checkDraggablePosition();
    },
    /**
     * 判断元素显示位置
     * 在窗口改变和move end时调用
     */
    checkDraggablePosition() {
      if (this.left + this.floatDragDom.width / 2 >= this.clientWidth / 2) {
        // 判断位置是往左往右滑动
        this.left = this.clientWidth - this.floatDragDom.width;
      } else {
        this.left = 0;
      }
      if (this.top < 0) {
        // 判断是否超出屏幕上沿
        this.top = 0;
      }
      if (this.top + this.floatDragDom.height >= this.clientHeight) {
        // 判断是否超出屏幕下沿
        this.top = this.clientHeight - this.floatDragDom.height;
      }
    }
  },
  beforeDestroy() {
    window.removeEventListener("scroll", this.handleScroll);
    window.removeEventListener("resize", this.handleResize);
  }
};
</script>
<style>
html,
body {
  overflow: hidden;
}
</style>
<style scoped lang="less">
.float-position {
  position: absolute;
  z-index: 10003;
  right: 0;
  top: 70%;
  width: 3.6em;
  height: 3.6em;
  background: deepskyblue;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0px 0px 10px 2px skyblue;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.8em;
  user-select: none;
}
.cart {
  border-radius: 50%;
  width: 5em;
  height: 5em;
  display: flex;
  align-items: center;
  justify-content: center;
}
.header-notice {
  display: inline-block;
  transition: all 0.3s;
  span {
    vertical-align: initial;
  }
  .notice-badge {
    color: inherit;
    .header-notice-icon {
      font-size: 16px;
      padding: 4px;
    }
  }
}
.drag-ball .drag-content {
  overflow-wrap: break-word;
  font-size: 14px;
  color: #fff;
  letter-spacing: 2px;
}
</style>

页面中使用:

<template>
  <div>
    <drag @handlepaly="handleaudioplay" style="cursor:pointer"></drag>
  </div>
</template>
<script>
import drag from "./dragbase";
export default {
  components: { drag },
  methods: {
    handleaudioplay() {
        console.log(123);
    }
  }
};
</script>

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

(0)

相关推荐

  • vue实现吸壁悬浮球

    本文实例为大家分享了vue实现吸壁悬浮球的具体代码,供大家参考,具体内容如下 最近接到一个需求,需要一个客服悬浮按钮,可以拖拽并吸壁到页面周边,我们一起看看吧 1.创建一个template,定义客服按钮,自定义v-drag指令 <template>   <div class="container">     <div       class="btn"       id="btn"       :style=&quo

  • vue实现悬浮球效果

    本文实例为大家分享了vue实现悬浮球效果的具体代码,供大家参考,具体内容如下 小球效果 小球移动效果图源码 <template>   <transition>     <div       ref="breathing_lamp"       class="breathing_lamp"       @click="onclick()"       @touchstart.stop="handleTouch

  • Vue使用vue-drag-resize生成悬浮拖拽小球

    本文实例为大家分享了使用vue-drag-resize生成悬浮拖拽小球的具体代码,供大家参考,具体内容如下 一.下载依赖 cnpm install  vue-drag-resize 二.main.js引用 import VueDragResize from 'vue-drag-resize' Vue.component('vue-drag-resize', VueDragResize) 三.创建组件 <template>   <vue-drag-resize id="moreM

  • vue实现div拖拽互换位置

    本文实例为大家分享了vue实现div拖拽互换位置的具体代码,供大家参考,具体内容如下 template模板 <transition-group tag="div" class="container"> <div class="item" v-for="(item,index) in items" :key="item.key" :style="{background:item.c

  • vue悬浮可拖拽悬浮按钮的实例代码

    前言 vue开发手机端悬浮按钮实现,可以拖拽,滚动的时候收到里边,不影响视线 github地址 使用,基于vue-cli3.0+webpack 4+vant ui + sass+ rem适配方案+axios封装,构建手机端模板脚手架 vue-h5-template 后续将发布各种商城组件组件,让商城简单高效开发 线上体验 使用 将 src/components文件夹下的s-icons组件放到你的组件目录下 使用组件 // template <template> <div> <

  • Vue.Draggable实现拖拽效果

    快速实现Vue.Draggable的拖拽效果,供大家参考,具体内容如下 1.下载包:npm install vuedraggable 配置:package.json "dependencies": { "element-ui": "^1.3.4", "less": "^2.7.2", "less-loader": "^4.0.4", "vue":

  • vue使用drag与drop实现拖拽的示例代码

    在功能中有一项是需要实现拖拽的.虽然最终项目没有采取这样的拖拽方式,但是,当初也是费了九牛二虎之力完成了这个功能.增加了对函数的更深理解.下面就再重现一下代码. 下面是代码片段: <div class="fav-fold-panel" v-if="!typeChange" draggable="true" @dragstart="drag($event)" @dragover="allowDrop($event

  • 基于Vue实现拖拽功能

    本文实例为大家分享了Vue实现拖拽功能的具体代码,供大家参考,具体内容如下 效果图: HTML代码: <div id="box"> 位置 <br>x:{{val.x}} <br>y:{{val.y}} <div v-drag="greet" id="drag" :style="style"> //注意这里要通过指令绑定函数将当前元素的位置数据传出来 </div> &l

  • 基于Vue实现拖拽效果

    效果图 demo1.gif 分清clientY pageY screenY layerY offsetY的区别 在我们想要做出拖拽这个效果的时候,我们需要分清这几个属性的区别,这几个属性都是计算鼠标点击的偏移值,我们需要对其进行了解才可以继续实现我们的拖拽效果 clientY 指的是距离可视页面左上角的距离 pageY 指的是距离可视页面左上角的距离(不受页面滚动影响) screenY 指的是距离屏幕左上角的距离 layerY 指的是找到它或它父级元素中最近具有定位的左上角距离 offsetY

  • Vue自定义指令拖拽功能示例

    下面给大家分享vue自定义指令拖拽功能代码,具体代码如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>实例方法</title> <meta name="viewport" content="width=device-width, initial-scale=1

随机推荐