欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue实现悬浮窗拖拽和靠边隐藏

程序员文章站 2024-01-11 20:37:10
...

预览

vue实现悬浮窗拖拽和靠边隐藏

组件

child.vue


<template>
  <div class="outBox">
    <div
      :class="['suspendBox', { move: !canDrag }]"
      :style="{top:top+'px',left:left+'px'}"
      @mousedown="start"
      @mousemove="move"
      @mouseup="stop"
      @mouseenter="enter"
      @mouseleave="leave"
    >
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  props:{
    ableMove: {type: Boolean, default: true},  //是否可移动
    ableHide: {type: Boolean, default: true},  //是否靠边隐藏
    hoverShow: {type: Boolean, default: true},  //图标隐藏时 鼠标悬浮即展示,否则点击展示
    distance: {type: Number, default: 5},  //距离边界多少px就隐藏
    defaultX: {type: Number, default: 1},  //初始横坐标百分比
    defaultY: {type: Number, default: 0.9}  //初始纵坐标百分比
  },
  data() {
    return {
      canDrag: false,
      isClick: true,
      x0: 0,
      y0: 0,
      top: null,
      left: null
    };
  },
  mounted() {
      let img = document.querySelector(".suspendBox");
      let box = document.querySelector(".outBox");
      this.left = (box.offsetWidth - img.offsetWidth) * this.defaultX;
      this.top = (box.offsetHeight - img.offsetHeight) * this.defaultY;
      setTimeout(()=>{
        this.hide()
      }, 1000)
  },
  methods: {
    start(e) {
      console.log("start");
      e.preventDefault();   //阻止默认的拖拽
      if (e.button == 0) {
        this.canDrag = this.ableMove;
        this.isClick = true;
        this.x0 = e.clientX;
        this.y0 = e.clientY;
      }
    },
    move(e) {
      console.log("move");
      if (this.canDrag == true) {
        this.isClick = false;
        let x = e.clientX - this.x0;
        let y = e.clientY - this.y0;
        let img = document.querySelector(".suspendBox");
        let box = document.querySelector(".outBox");
        if (
          img.offsetLeft + x < 0 ||
          img.offsetTop + y < 0 ||
          img.offsetLeft + x > box.offsetWidth - img.offsetWidth ||
          img.offsetTop + y > box.offsetHeight - img.offsetHeight
        ) {
          return false;
        }
        this.left = img.offsetLeft + x;
        this.top = img.offsetTop + y;
        this.x0 = e.clientX;
        this.y0 = e.clientY;
      }
    },
    stop() {
      this.canDrag = false;
      console.log("stop");
      this.show();
    },
    enter() {
      console.log("enter");
      if (this.hoverShow) {
        this.show();
      }
    },
    leave() {
      console.log("leave");
      this.canDrag = false;
      this.hide();
    },
    show() {
      let img = document.querySelector(".suspendBox");
      let box = document.querySelector(".outBox");
      if (img.offsetLeft < 0) {
        this.left = 0;
      } else if (img.offsetLeft > box.offsetWidth - img.offsetWidth) {
        this.left = box.offsetWidth - img.offsetWidth
      } else if(this.isClick){
        this.clickEvent()
      }
    },
    hide() {
      if (this.ableHide) {
        console.log("hide");
        let img = document.querySelector(".suspendBox");
        let box = document.querySelector(".outBox");
        if (!this.canDrag && img.offsetLeft < this.distance) {
          this.left = -img.offsetWidth * 2 / 3;
        } else if (!this.canDrag && img.offsetLeft > box.offsetWidth - img.offsetWidth - this.distance) {
          this.left = box.offsetWidth - img.offsetWidth / 3
        }
      }
    },
    clickEvent() {      //悬浮窗的点击事件
      console.log("悬浮窗的点击事件");
    },
  },
};
</script>
<style scoped>
.outBox {
  width: 100%;
  height: 100%;
  position: absolute;
  overflow: hidden;
  z-index:100;
  pointer-events: none;
}
.suspendBox {
  position: absolute;
  pointer-events: auto;
}
.move {
  transition: 0.3s linear;
  -moz-transition: 0.3s linear; /* Firefox 4 */
  -webkit-transition: 0.3s linear; /* Safari 和 Chrome */
  -o-transition: 0.3s linear; /* Opera */
}
</style>

如何使用

1.新建上述组件

(点击事件可写在clickEvent方法里)

2.在父组件中引入即可

例如
father.vue

<template>
  <div class="father">
    <child>
      <img width="50px" height="50px" src="../assets/logo.png" alt="" />
    </child>
    <div>
      <p v-for="index in 10" :key="index">其余内容</p>
    </div>
  </div>
</template>

<script>
import child from "./child";
export default {
  components: {
    child,
  },
  data() {
    return {
    };
  },
  methods: {
  },
};
</script>
<style scoped>
.father {
  margin: auto;
  position: relative;
  width: 500px;
  height: 600px;
  background-color: cyan;
}
</style>

注意点:图片可自行更改
father样式可自行更改,不过child组件的父元素必须是定位元素,即要有position:relative/absolute/fixed…

参数

参数见child.vue里的props

相关标签: vue