h5(移动端)封装悬浮按钮

360 阅读1分钟

按钮可以替换为图片/动图,根据需求选择

<template>
  <div class="float_button">
    <div
      @click="onBtnClicked"
      ref="floatButton"
      class="float_info"
      :style="{
        width: itemWidth + 'px',
        height: itemHeight + 'px',
        left: left + 'px',
        top: top + 'px',
        bottom: bottom + 'px'
      }"
    >
      <div>按钮</div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      clientWidth: 0,
      clientHeight: 0,
      timer: null,
      currentTop: 0,
      left: 0,
      top: 0,
      bottom: 0
    };
  },
  props: {
    text: {
      // 按钮文本内容
      type: String,
      default: ""
    },
    itemWidth: {
      // 悬浮按钮宽度
      type: Number,
      default: 55
    },
    itemHeight: {
      // 悬浮按钮高度
      type: Number,
      default: 55
    },
    gapWidth: {
      // 距离左右两边距离
      type: Number,
      default: 10
    },
    coefficientHeight: {
      // 从上到下距离比例
      type: Number,
      default: 0.55
    }
  },
  created() {
    this.clientWidth = document.documentElement.clientWidth;
    this.clientHeight = document.documentElement.clientHeight;
    this.left = this.clientWidth - this.itemWidth - this.gapWidth;
    this.top = this.clientHeight * this.coefficientHeight;
    this.bottom = this.clientHeight * this.coefficientHeight;
  },
  methods: {
    onBtnClicked() {
      this.$emit("onFloatBtnClicked");
    },
    handleScrollStart() {
      this.timer && clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.handleScrollEnd();
      }, 300);
      this.currentTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (this.left > this.clientWidth / 2) {
        this.left = this.clientWidth - this.itemWidth / 2;
      } else {
        this.left = -this.itemWidth / 2;
      }
    },
    handleScrollEnd() {
      let scrollTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      if (scrollTop === this.currentTop) {
        if (this.left > this.clientWidth / 2) {
          this.left = this.clientWidth - this.itemWidth - this.gapWidth;
        } else {
          this.left = this.gapWidth;
        }
        clearTimeout(this.timer);
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      const floatButton = this.$refs.floatButton;
      floatButton.addEventListener("touchstart", () => {
        floatButton.style.transition = "none";
      });

      // 在拖拽的过程中,组件应该跟随手指的移动而移动。
      floatButton.addEventListener("touchmove", e => {
        if (e.targetTouches.length === 1) {
          // 一根手指
          let touch = e.targetTouches[0];
          this.left = touch.clientX - 20;
          this.top = touch.clientY - 25;
          this.bottom = touch.clientY;
        }
      });

      // 拖拽结束以后,重新调整组件的位置并重新设置过度动画。
      floatButton.addEventListener("touchend", () => {
        floatButton.style.transition = "all 0.3s";
        if (this.left > document.documentElement.clientWidth / 2) {
          this.left = document.documentElement.clientWidth - 65;
        } else {
          this.left = 10;
        }
        if (this.top < document.documentElement.clientTop / 2) {
          this.top = this.clientHeight * this.coefficientHeight;
        }
        if (this.bottom >= document.documentElement.clientHeight) {
          this.top = this.clientHeight * this.coefficientHeight;
        }
      });
    });
  },
  beforeDestroy() {
    // 添加监听页面滚动
    window.removeEventListener("scroll", this.handleScrollStart);
  }
};
</script>
<style lang="scss">
@-webkit-keyframes welfare {
  10% {
    transform: rotate(15deg);
  }
  20% {
    transform: rotate(-10deg);
  }
  30% {
    transform: rotate(5deg);
  }
  40% {
    transform: rotate(-5deg);
  }
  50% {
    transform: rotate(5deg);
  }
  100% {
    transform: rotate(-5deg);
  }
}
.float_button {
  .float_info {
    transition: all 0.3s;
    position: fixed;
    //bottom: 436px;
    right: 0;
    display: flex;
    flex-flow: column;
    justify-content: center;
    align-items: center;
    z-index: 100;
    cursor: pointer;
    -webkit-animation: welfare 3s linear infinite;
  }
}
</style>