实现贴边悬浮可拖动的交互效果

最新更新时间:2019年10月15日09:51:32
《猛戳-查看我的博客地图-总有你意想不到的惊喜》

本文内容:一般情况下,在应用的首页,会有一个贴边的、悬浮的、可拖动的按钮,用来快速进入具体的某个页面,或者用来调起客服,或者其他信息。

概述

本文使用 react 框架,采用组件化方案实现这个交互效果,并且完全兼容 Android 和 iOS 双端。尤其是针对 iOS 端,当页面滚动到上下边界时出现的橡皮筋效果,也做了很好的处理。方案简单易懂,希望大家参考和学习。

父组件
import React from 'react'
import Child from './Child'
export default class Parent extends React{

  constructor(props){}

  componentDidMount() {}

  render(){
    return <div id='parent' className={styles.container}>
    	<Child/>
    </div>
  }
子组件

此处的小助手是可拖动的的这个子组件

import React from 'react'
export default class Child extends React.PureComponent{

  constructor(props){
    super(props);
    this.state = {}
    this.relativeY = 0;//手指触摸 小助手 的点距离该元素顶部的距离
    this.reachTop = false;//移动 小助手 是否超过屏幕顶部
    this.reachBottom = false;//移动 小助手 是否超过屏幕底部
    this.childtDom = null;
    this.html = null;
  }

  componentDidMount() {
    let _this = this;
    this.childtDom = document.getElementById('child');
    this.html = document.documentElement;
    //页面初始化 禁止body滚动-iOS页面上下滚动的橡皮筋效果
    //如果使用 touchstart childtDom上的onClick事件失效
    document.body.addEventListener('touchmove', _this.preventScroll, {passive: false});
    //开始触摸parent 解除body滚动
    document.getElementById('parent').addEventListener('touchstart', function (e) {
      //触摸的元素不是小助手 解除禁止body滚动
      //触摸的元素是小助手 body处于禁止滚动状态
      if(e.target.id != 'child'){
        document.body.removeEventListener('touchmove', _this.preventScroll);
      }
    }, {passive: false});
    //触摸parent结束 禁止body滚动-iOS页面上下滚动的橡皮筋效果
    document.getElementById('parent').addEventListener('touchend', function () {
      document.body.addEventListener('touchmove', _this.preventScroll, {passive: false});
    }, {passive: false});
  }

  componentWillUnmount() {
    //组件卸载-卸载事件
    document.body.removeEventListener('touchmove', this.preventScroll);
  }

  /**
   * 手指放在 小助手 上移动
   * @param event
   * @return
   */
  onTouchMove(e){
    let clientY = e.touches[0].clientY;//手指触摸屏幕的点距离文档顶部的距离 文档总高度可能会超过屏幕高度
    let smallAssistantTop = clientY + this.relativeY;//小助手 相对屏幕顶部绝对定位的距离
    this.childtDom.style.top = smallAssistantTop + 'px'
    if(smallAssistantTop < 0){
      this.reachTop = true;
    }
    if(smallAssistantTop > this.html.offsetHeight - 70){
      this.reachBottom = true;
    }
  }

  /**
   * 手指放在 小助手
   * @param event
   * @return
   */
  onTouchStart(e){
    this.relativeY = e.target.offsetTop - e.touches[0].clientY
  }

  /**
   * 手指离开 小助手
   * @param event
   * @return
   */
  onTouchEnd(){
    if(this.reachTop){
      this.childtDom.style.top = 0 + 'px'
      this.reachTop = false;
    }
    if(this.reachBottom){
      this.childtDom.style.top = this.html.offsetHeight - 70 + 'px'
      this.reachBottom = false;
    }
  }

  /**
   * 阻止页面滚动
   * @param
   * @return
   */
  preventScroll(e){
    e.preventDefault();
  }
  
  render(){
    return <div
      id='child'
      style={{position:'fixed',bottom:'100px',width:'70px',height:'70px'}}
      onTouchMove={(e)=>{this.onTouchMove(e)}}
      onTouchStart={(e)=>{this.onTouchStart(e)}}
      onTouchEnd={(e)=>{this.onTouchEnd(e)}}
    >
      <img style={{width:'100%',height:'100%',pointerEvents:'none'}} src={require('./a.gif')}/>
    </div>
  }
}
参考资料

感谢阅读,欢迎评论^-^

打赏我吧^-^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值