• xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!


    scroll tabs

    https://github.com/NervJS/taro-ui/blob/dev/src/components/tabs/index.tsx

    https://github.com/NervJS/taro-ui/blob/dev/src/components/tabs/index.tsx#L78

    
      public constructor(props: AtTabsProps) {
        super(props)
        this.state = {
          _scrollLeft: 0,
          _scrollTop: 0,
          _scrollIntoView: ''
        }
        this._tabId = isTest() ? 'tabs-AOTU2018' : uuid()
        // 触摸时的原点
        this._touchDot = 0
        // 定时器
        this._timer = null
        // 滑动时间间隔
        this._interval = 0
        // 是否已经在滑动
        this._isMoving = false
      }
    
      private updateState = (idx: number): void => {
        if (this.props.scroll) {
          // 标签栏滚动
          switch (ENV) {
            case Taro.ENV_TYPE.WEAPP:
            case Taro.ENV_TYPE.ALIPAY:
            case Taro.ENV_TYPE.SWAN: {
              const index = Math.max(idx - 1, 0)
              this.setState({
                _scrollIntoView: `tab${index}`
              })
              break
            }
            case Taro.ENV_TYPE.WEB: {
              const index = Math.max(idx - 1, 0)
              const prevTabItem = this.tabHeaderRef.childNodes[index]
              prevTabItem &&
                this.setState({
                  _scrollTop: prevTabItem.offsetTop,
                  _scrollLeft: prevTabItem.offsetLeft
                })
              break
            }
            default: {
              console.warn('AtTab 组件在该环境还未适配')
              break
            }
          }
        }
      }
    
      private handleClick(index: number, event: CommonEvent): void {
        this.props.onClick(index, event)
      }
    
      private handleTouchStart(e: ITouchEvent): void {
        const { swipeable, tabDirection } = this.props
        if (!swipeable || tabDirection === 'vertical') return
        // 获取触摸时的原点
        this._touchDot = e.touches[0].pageX
        // 使用js计时器记录时间
        this._timer = setInterval(() => {
          this._interval++
        }, 100)
      }
    
      private handleTouchMove(e: ITouchEvent): void {
        const { swipeable, tabDirection, current, tabList } = this.props
        if (!swipeable || tabDirection === 'vertical') return
    
        const touchMove = e.touches[0].pageX
        const moveDistance = touchMove - this._touchDot
        const maxIndex = tabList.length
    
        if (
          !this._isMoving &&
          this._interval < MAX_INTERVAL &&
          this._touchDot > 20
        ) {
          // 向左滑动
          if (current + 1 < maxIndex && moveDistance <= -MIN_DISTANCE) {
            this._isMoving = true
            this.handleClick(current + 1, e)
    
            // 向右滑动
          } else if (current - 1 >= 0 && moveDistance >= MIN_DISTANCE) {
            this._isMoving = true
            this.handleClick(current - 1, e)
          }
        }
      }
    
      private handleTouchEnd(): void {
        const { swipeable, tabDirection } = this.props
        if (!swipeable || tabDirection === 'vertical') return
    
        clearInterval(this._timer as NodeJS.Timeout)
        this._interval = 0
        this._isMoving = false
      }
    
    
    
    
      public render(): JSX.Element {
        const {
          customStyle,
          className,
          height,
          tabDirection,
          animated,
          tabList,
          scroll,
          current
        } = this.props
        const { _scrollLeft, _scrollTop, _scrollIntoView } = this.state
    
        const heightStyle = { height }
        const underlineStyle = {
          height: tabDirection === 'vertical' ? `${tabList.length * 100}%` : '1PX',
           tabDirection === 'horizontal' ? `${tabList.length * 100}%` : '1PX'
        }
        const bodyStyle: React.CSSProperties = {}
        let transformStyle = `translate3d(0px, -${current * 100}%, 0px)`
        if (tabDirection === 'horizontal') {
          transformStyle = `translate3d(-${current * 100}%, 0px, 0px)`
        }
        Object.assign(bodyStyle, {
          transform: transformStyle,
          '-webkit-transform': transformStyle
        })
        if (!animated) {
          bodyStyle.transition = 'unset'
        }
    
        const tabItems = tabList.map((item, idx) => {
          const itemCls = classNames({
            'at-tabs__item': true,
            'at-tabs__item--active': current === idx
          })
    
          return (
            <View
              className={itemCls}
              id={`tab${idx}`}
              key={item.title}
              onClick={this.handleClick.bind(this, idx)}
            >
              {item.title}
              <View className='at-tabs__item-underline'></View>
            </View>
          )
        })
        const rootCls = classNames(
          {
            'at-tabs': true,
            'at-tabs--scroll': scroll,
            [`at-tabs--${tabDirection}`]: true,
            [`at-tabs--${ENV}`]: true
          },
          className
        )
        const scrollX = tabDirection === 'horizontal'
        const scrollY = tabDirection === 'vertical'
    
        return (
          <View
            className={rootCls}
            style={this.mergeStyle(heightStyle, customStyle!)}
          >
            {scroll ? (
              <ScrollView
                id={this._tabId}
                className='at-tabs__header'
                style={heightStyle}
                scrollX={scrollX}
                scrollY={scrollY}
                scrollWithAnimation
                scrollLeft={_scrollLeft}
                scrollTop={_scrollTop}
                scrollIntoView={_scrollIntoView}
              >
                {tabItems}
              </ScrollView>
            ) : (
              <View id={this._tabId} className='at-tabs__header'>
                {tabItems}
              </View>
            )}
            <View
              className='at-tabs__body'
              onTouchStart={this.handleTouchStart.bind(this)}
              onTouchEnd={this.handleTouchEnd.bind(this)}
              onTouchMove={this.handleTouchMove.bind(this)}
              style={this.mergeStyle(bodyStyle, heightStyle)}
            >
              <View className='at-tabs__underline' style={underlineStyle}></View>
              {this.props.children}
            </View>
          </View>
        )
      }
    
    
    

    demo


  • 相关阅读:
    Android Studio使用笔记
    Android Material Design之在RecyclerView中嵌套CardView实现
    RR 和RC 幻读问题
    mysql rr和rc区别
    7.2 Database Backup Methods 数据备份方法:
    7.1 Backup and Recovery Types 备份和恢复类型
    Chapter 7 Backup and Recovery 备份和恢复:
    mysqldump 一些参数体验
    (?m) 可以让.去匹配换行
    perl 正则前导字符
  • 原文地址:https://www.cnblogs.com/xgqfrms/p/12609914.html
Copyright © 2020-2023  润新知