React实现类似淘宝tab居中切换效果

调休计算器
• 阅读 2766

效果

React实现类似淘宝tab居中切换效果

DOM布局

const label = {
  lettersort: false,
  paramname: "label",
  paramid: 0,
  title: "车源列表筛选项",
  option: [{
      value: 1,
      text: "全部"
    },
    {
      value: 2,
      text: "本地求购"
    },
    {
      value: 3,
      text: "精准收车"
    },
    {
      value: 4,
      text: "全国收车"
    },
    {
      value: 5,
      text: "同行询价"
    },
    {
      value: 6,
      text: "可批可售"
    },
    {
      value: 7,
      text: "车抵贷款"
    },
    {
      value: 8,
      text: "消费贷款"
    },
    {
      value: 9,
      text: "商家库容"
    },
    {
      value: 10,
      text: "代理合作"
    },
    {
      value: 11,
      text: "过户转籍"
    },
    {
      value: 12,
      text: "寻车拖车"
    },
    {
      value: 13,
      text: "解压抵押"
    },
    {
      value: 14,
      text: "抵押核验"
    }
  ]
}
filterDom = () => {
    let filterJson = label;
    let arr = filterJson.option;
    return (
        <div ref="filterBar" className="filter-list">
            {arr.map((item, index) => {
                if (item.value == this.state.filterSelect) {
                    return (
                        <div
                            ref={item.value}
                            className="filter-item active"
                            key={index}
                            value={item.value}>
                            {item.text}
                            <div className="zhishi"></div>
                        </div>
                    );
                } else {
                    return (
                        <div
                            className="filter-item"
                            onClick={() => {
                                this.filterBarClick(item);
                            }}
                            ref={item.value}
                            key={index}
                            value={item.value}>
                            {item.text}
                        </div>
                    );
                }
            })}
        </div>
    );
};
render(){
  return(
    <div>
      ...
      <div className="filter-content" style={{ display: this.state.filterBarShow }}>
          {this.filterDom()}
          <div className="shadow"></div>
          {/* 按钮和占位 */}
          <div
              className="filte-btn-content"
              onClick={() => {
                  this.filterBtnClick();
              }}>
              <div className="filte-btn"></div>
          </div>
      </div>
      ...
    </div>
  )
}

scss样式表

.filter {
  width: 100%;
  // position: fixed;
}
.filter-content {
    overflow: hidden;
    padding-right: pxToRem(27px);
    position: relative;
    background: #fff;
    .filter-list {
        display: flex;
        overflow-x: auto;
        justify-content: space-between;
        height: pxToRem(90px);
        color: #333333;
        align-items: center;
        -webkit-overflow-scrolling: touch;
        font-size: pxToRem(32px);
        font-family:PingFangSC-Light,PingFang SC;
        font-weight:300;
        background: #fff;
        margin-right: pxToRem(100px);
        .filter-item {
            text-align: center;
            display: flex;
            // flex-basis: 17px;
            flex-shrink: 0;
            white-space: nowrap;
            padding: 0 pxToRem(25px);
            background: #fff;
            height: pxToRem(90px);
            align-items: center;
            justify-content: center;
        }
        .active{
            font-size: pxToRem(36px);
            font-weight: 600;
            height: pxToRem(90px);
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            flex: 1;
            flex-direction: column;
        }
        .zhishi{
            background: url("./../img/zhishi.png");
            background-repeat: no-repeat;
            background-size: 100%;
            width: pxToRem(25px);
            height: pxToRem(6px);
            position: absolute;
            bottom: pxToRem(10px);;
            left: 50%;
            transform: translate(-50%, 0);
            z-index: 999;
        }
    }
    
    .shadow{
        height: pxToRem(90px);
        width: pxToRem(133px);
        position: absolute;
        right: pxToRem(101px);
        top: 0;
        background:linear-gradient(270deg,rgba(255,255,255,1) 0%,rgba(255,255,255,0.14) 100%);
        pointer-events: none;
    }
    .filte-btn{
        background: url("./../img/shaixuan.png");
        background-repeat: no-repeat;
        background-size: 100%;
        width: pxToRem(40px);
        height: pxToRem(40px);
    }
    .filte-btn-content {
        height: pxToRem(90px);
        position: absolute;
        right: pxToRem(27px);
        top: 0;
        background: #fff;
        width: pxToRem(74px);
        display: flex;
        align-items: center;
        justify-content: flex-end;
    }
}

实现

想要居中展示首先是需要找到中心点,然后在点击是计算偏移量,把对应的标签滚动到中心位置

filterBarClick = param => {
        const { value, text } = param;
        this.setState({
            filterSelect: value
        });
        let dom = this.refs;
        //获取点击时当前标签的DOM
        let valDom = dom[value];
        //获取标签父元素DOM
        let contentDom = dom.filterBar;
        //计算当前标签到最左侧的宽度
        let valLeft = valDom.offsetLeft;
        //计算当前标签本身的宽度
        let valWidth = valDom.clientWidth;
        //当前标签中心点到最左侧的距离
        let valCenter = valLeft + valWidth / 2;
        //可视屏幕宽度
        let clientWidth = document.querySelector('body').offsetWidth;
        //可视屏幕中心点(减去的30是列表两边的15像素的留白)
        let center = (clientWidth - 30) / 2;
        //计算当前标签中心点和屏幕中心点的偏移量 然后滚动相应的距离
        if (valCenter > center) {
            contentDom.scrollTo({
                left: valCenter - center,
                behavior: 'smooth'
            });
        } else {
            contentDom.scrollTo({
                left: 0,
                behavior: 'smooth'
            });
        }
    };
点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
李志宽 李志宽
2年前
Linux 总结的这几个最危险的命令,谁用谁知道!
!image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/f8f28d469fb86f20e9a08dd62055c841.png)!image(https://imghelloworld.osscnbeiji
Wesley13 Wesley13
4年前
TAB切换效果
<!DOCTYPEhtmlPUBLIC"//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd"<htmlxmlns"http://www.w3.org/1999/xhtml"<head<
似梦清欢 似梦清欢
3年前
链表
线性表的链式存储实现称为链表。!image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/eb5f24c795ece73a1f77156aa7131869.png)
梦
5年前
微信小程序new Date()转换时间异常问题
微信小程序苹果手机页面上显示时间异常,安卓机正常问题image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b691e1230e2f15efbd81fe11ef734d4f.png)错误代码vardate'2021030617:00:00'vardateT
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
4年前
MFC tab 绘制效果
CDC pDC &MemDC;CRect rectTabrcWindow;rectTab.left100;rectTab.rightrectTab.left100;rectTab.top5;rectTab.bottomrectTab.top25;CList<
CRM从哪些方面进行了管理?
我们将CRM(https://www.sap.cn/products/crm.html!image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/17e2d96568a98f0
皕杰报表的关系数据库数据源配置
1.首先在设计器里面!image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b57243ea109235edcb344472099038a3.png)!image