vue 页面悬浮图标 滑动。和影响背景页面滑动问题等

47 篇文章 0 订阅
16 篇文章 0 订阅

直接上代码先 。组件 。次组件功能没有全部完善,需要自己改动 float.vue

<template>
  <div class="ys-float-btn" :style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','top':top+'px'}"
       ref="div"
       @touchstart.stop="gtouchstart()"
       @touchmove.stop="gtouchmove()"
       @touchend.stop="gtouchend()"
       @click.stop ="onBtnClicked">
    <slot></slot>
    <!-- <p>{{text}}</p> -->
  </div>
</template>

<script>
  export default {
    name: "FloatImgBtn",
    props:{
// 背景页面需要设置宽度。或者滑动不会顺畅
      itemWidth:{
        type:Number,
        default:60
      },
      itemHeight:{
        type:Number,
        default:60
      },
      gapWidth:{ // 距离边距
        type:Number,
        default:-20
      },
      coefficientHeight:{ // 默认停留位置等比高度
        type:Number,
        default:0.4
      },
      gapHeight:{ // 移动最小距离底部高度
        type:Number,
        default:60
      }
    },
    data(){
      return{
        timer:null,
        currentTop:0,
        clientWidth:0,
        clientHeight:0,
        left:0,
        top:0,
      }
    },
    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;
    },
    mounted(){
      window.addEventListener('scroll', this.handleScrollStart);
      this.$nextTick(()=>{
        const div = this.$refs.div;
        div.addEventListener("touchstart",()=>{
          div.style.transition = 'none';
        });
        div.addEventListener("touchmove",(e)=>{
          if (e.targetTouches.length === 1) {
            let touch = event.targetTouches[0];
            this.left = touch.clientX - this.itemWidth/2;
            this.top = touch.clientY - this.itemHeight/2;
            // console.log(this.top,this.clientHeight)
            //  console.log(touch)
          }
        });
        div.addEventListener("touchend",()=>{
          div.style.transition = 'all 0.3s';
           if(this.left>this.clientWidth/2){ // 右边
             this.left = this.clientWidth - this.itemWidth;
             setTimeout(()=>{ // 停止移动动画
                this.left = this.left - this.gapWidth;
            },500);
           }else{ // 左边
            //  this.left = this.gapWidth; 
             this.left = 0;
             setTimeout(()=>{ // 停止移动动画
                this.left = this.left + this.gapWidth;
            },500);
           }

           if(this.top > this.clientHeight-this.gapHeight){ // 底部位置限制
              this.top = this.clientHeight-this.gapHeight*2;
           }
            if(this.top < 0 ){ // 滑动到头部位置限制
              this.top = 0;
           }
        });

      });
    },
    beforeDestroy(){
      window.removeEventListener('scroll', this.handleScrollStart);
    },
    methods:{
        gtouchstart(){
            //真正长按后应该执行的内容           
            console.log("长按事件触发发");
         },
         //如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按
        gtouchmove(){
            // console.log('移动')
            this.$emit('scrollStart');  
            // this.handleScrollStart();
            // alert("取消了");
        },
        //手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件
        gtouchend(){
            // console.log('9933')
            this.$emit('scrollEnd')
            console.log("释放");
        },
      onBtnClicked(){
        this.$emit("onFloatBtnClicked");
        // console.log('0003')
      },
      handleScrollStart(){ // 上下滑动时 背部滑动时触发。但这个会有问题。所以背景页面样式需要加 overflow-y: auto; 防止滑动触发背景页面滑动
        this.timer&&clearTimeout(this.timer);
        this.timer = setTimeout(()=>{
          this.handleScrollEnd();
        },300);
        this.currentTop = document.documentElement.scrollTop || document.body.scrollTop;
        console.log('移动',this.currentTop)
        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;
          }
          if(this.top > this.clientHeight-this.gapHeight){
              this.top = this.clientHeight-this.gapHeight*2;
          }
          clearTimeout(this.timer);
        }
      }
    }
  }
</script>

<style lang="less" scoped>
  .ys-float-btn{
    // background:rgb(255,255,255);
    // box-shadow:0 2px 10px 0 rgba(0,0,0,0.1);
    // border-radius:50%;
    // color: #666666;
    z-index: 20;
    transition: all 0.3s;

    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    position: fixed;
    // bottom: 20vw;

    // img{
    //   width: 50%;
    //   height: 50%;
    //   object-fit: contain;
    //   margin-bottom: 3px;
    // }

    // p{
    //   font-size:7px;
    // }
  }
</style>


发现原生的方法 在苹果下面 滑动的时候会闪动,不顺畅
改成

<template>
  <div class="ys-float-btn" :style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','top':top+'px'}"
       ref="div"
       @touchstart.stop="gtouchstart"
       @touchmove.stop="gtouchmove"
       @touchend.stop="gtouchend"
       @click.stop ="onBtnClicked">
    <slot></slot>
    <!-- <p>{{text}}</p> -->
  </div>
</template>

<script>
  export default {
    name: "FloatImgBtn",
    props:{
// 背景页面需要设置宽度。或者滑动不会顺畅
      itemWidth:{
        type:Number,
        default:60
      },
      itemHeight:{
        type:Number,
        default:60
      },
      gapWidth:{ // 距离边距
        type:Number,
        default:-25
      },
      coefficientHeight:{ // 默认停留位置等比高度
        type:Number,
        default:0.4
      },
      gapHeight:{ // 移动最小距离底部高度
        type:Number,
        default:60
      },
      timeWidth:{ // 半隐藏延迟时间 毫秒
        type:Number,
        default: 1500
      }
    },
    data(){
      return{
        timer:null,
        currentTop:0,
        clientWidth:0,
        clientHeight:0,
        left:0,
        top:0,
      }
    },
    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;
    },
    mounted(){
    //   window.addEventListener('scroll', this.handleScrollStart);
    //   this.$nextTick(()=>{
        // const div = this.$refs.div;
        // div.addEventListener("touchstart",()=>{
        // //   div.style.transition = 'none';
        // });
        // div.addEventListener("touchmove",(e)=>{
        //   if (e.targetTouches.length === 1) {
        //     let touch = event.targetTouches[0];
        //     this.left = touch.clientX - this.itemWidth/2;
        //     this.top = touch.clientY - this.itemHeight/2;
        //     // console.log(this.top,this.clientHeight)
        //      console.log('移动2')
        //   }
        // });
        // div.addEventListener("touchend",()=>{
        // //   div.style.transition = 'all 0.3s';
        //   console.log('停止2')
        //   alert('停止3')
        //    if(this.left>this.clientWidth/2){ // 右边
        //      this.left = this.clientWidth - this.itemWidth;
        //     //  setTimeout(()=>{ // 停止移动动画
        //     //     this.left = this.left - this.gapWidth;
        //     // },this.timeWidth);
        //    }else{ // 左边
        //     //  this.left = this.gapWidth; 
        //      this.left = 0;
        //     //  setTimeout(()=>{ // 停止移动动画
        //     //     this.left = this.left + this.gapWidth;
        //     // },this.timeWidth);
        //    }

        //    if(this.top > this.clientHeight-this.gapHeight){ // 底部位置限制
        //       this.top = this.clientHeight-this.gapHeight*2;
        //    }
        //     if(this.top < 0 ){ // 滑动到头部位置限制
        //       this.top = 0;
        //    }
        // });

    //   });
    },
    beforeDestroy(){
    //   window.removeEventListener('scroll', this.handleScrollStart);
    },
    methods:{
        gtouchstart(){
            //真正长按后应该执行的内容 
            let div = this.$refs.div;
             div.style.transition = 'none';          
            console.log("长按事件触发发");
         },
         //如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按
        gtouchmove(e){
            console.log('移动',e)
        if (e.targetTouches.length === 1) {
            let touch = e.targetTouches[0];
            this.left = touch.clientX - this.itemWidth/2;
            this.top = touch.clientY - this.itemHeight/2;
            // console.log(this.top,this.clientHeight)
             console.log('移动2')
          }
            this.$emit('scrollStart');  
            // this.handleScrollStart();
            // alert("取消了");
        },
        //手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件
        gtouchend(){
            // console.log('9933')
          this.$emit('scrollEnd')
          let div = this.$refs.div;
          div.style.transition = 'all 0.3s';
          if(this.left>this.clientWidth/2){ // 右边
             this.left = this.clientWidth - this.itemWidth;
             setTimeout(()=>{ // 停止移动动画
                this.left = this.left - this.gapWidth;
            },this.timeWidth);
           }else{ // 左边
            //  this.left = this.gapWidth; 
             this.left = 0;
             setTimeout(()=>{ // 停止移动动画
                this.left = this.left + this.gapWidth;
            },this.timeWidth);
           }

           if(this.top > this.clientHeight-this.gapHeight){ // 底部位置限制
              this.top = this.clientHeight-this.gapHeight*2;
           }
            if(this.top < 0 ){ // 滑动到头部位置限制
              this.top = 0;
           }
        },
      onBtnClicked(){
        this.$emit("onFloatBtnClicked");
        // console.log('0003')
      },
      handleScrollStart(){ // 上下滑动时 背部滑动时触发。但这个会有问题。所以背景页面样式需要加 overflow-y: auto; 防止滑动触发背景页面滑动
        this.timer&&clearTimeout(this.timer);
        this.timer = setTimeout(()=>{
          this.handleScrollEnd();
        },300);
        this.currentTop = document.documentElement.scrollTop || document.body.scrollTop;
        console.log('移动',this.currentTop)
        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;
          }
          if(this.top > this.clientHeight-this.gapHeight){
              this.top = this.clientHeight-this.gapHeight*2;
          }
          clearTimeout(this.timer);
        }
      }
    }
  }
</script>

<style lang="less" scoped>
  .ys-float-btn{
    // background:rgb(255,255,255);
    // box-shadow:0 2px 10px 0 rgba(0,0,0,0.1);
    // border-radius:50%;
    // color: #666666;
    z-index: 20;
    transition: all 0.3s;

    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    position: fixed;
    // bottom: 20vw;

    // img{
    //   width: 50%;
    //   height: 50%;
    //   object-fit: contain;
    //   margin-bottom: 3px;
    // }

    // p{
    //   font-size:7px;
    // }
  }
</style>

背景页面引用

<float>
     <a
    :href="xxxx"
  >
    <img src="../assets/tpjia.png" style="width: 1rem;" alt />
  </a>
</float>
import float from "@/components/float";
  components: {
    float
  },

需要注意,背景页面样式。否则会导致 拖动图标的时候 ,影响背景页面滑动

.index-body {
  position: absolute;
  overflow-y: auto;
  // left: 0.3rem;
  // 此样式会影响浮标滑动,需要设置宽度
  width: calc(100% - 0.6rem);
  top: 0;
  bottom: 0;
  // right: 0.3rem;
  // padding-bottom: 1.2rem;
  padding-left: 0.3rem;
  padding-right: 0.3rem;
  background: #FAFAFA;
}

滑动页面。第一个overflow-y: auto; 值语序Y轴。 可以避免拖动浮标时,影响背景滑动
width: calc(100% - 0.6rem); 需要设置宽度,组件计算滑动,和距离。如果没有设置会有影响

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值