轮播效果的单选组按钮:React + antd

337 阅读2分钟

需求

  1. 单选组按钮
  2. 不确定待选项长度
  3. 左右滑切换待选项
  4. 根据待选项长度自动隐藏/显示切换按钮 效果如下:屏幕录制的软件有点问题,鼠标的pointer可能不准,应该不影响展示。

slideBtn.gif

代码

导入所需的库

import React, { useState, useEffect } from 'react'
import {
  Radio,
} from 'antd'
import 'antd/dist/antd.css';
import './style.css';

组件结构

<div className="container">
  {/* 控制滑动的左右按钮 */}
  <button
    className="left-arrow"
    id='left'
    onClick={handleMove}
    >
    &lt;</button>
  {
    (subWidth > fatherwidth) && (
      <button 
        className="right-arrow" 
        id='right' 
        onClick={handleMove}
        >
        &gt;
      </button>
    )
  }
  <div className="sub-container" style={{ width: subWidth }}>
    {/* 单选按钮组 */}
    <Radio.Group
      name="slidebtn"
      optionType="button"
      buttonStyle="solid"
      defaultValue={slideData[0].id}
      onChange={key => console.log("选中的按钮的key为:", key)}
    >
      {
        slideData.map(item =>
           <Radio 
             value={item.id} 
             className="radiobtn" 
             style={{ marginRight: '20px' }}
             >
             {item.text}
            </Radio>
         )
      }
    </Radio.Group>
  </div>
</div>

关键样式

// style.css
.container {
  width: 500px;
  height: 32px;
  margin: 0 auto;
  border: 1px solid #333333;
  overflow: hidden;
  position: relative;
  /* background-color: #bfc; */

}
.sub-container {
  position: relative;
  left: 0;
  width: 1000px;
  transition: left 2s;

}
.right-arrow, .left-arrow {
  display: block;
  height: 100%;
  line-height: 28px;
  width: 24px;
  position: absolute;
  top: 0;
  text-align: center;
  background-color: #fff;
  z-index: 999;
  border: 1px solid #efefef;
}

.left-arrow {
  display: none;
  left: 0;
}
.right-arrow {
  right: 0;
}

常量/状态

// 父容器的固定宽度
const fatherwidth = 500
// 子容器
const subcon = document.querySelector(".sub-container")
// 子容器的宽度根据内容而定
const [subWidth, setSubWidth] = useState(0)
// 要渲染的单选组待选项
const { data } = props
const [slideData, setSlideData] = useState(data)

Notes: 本文设定待选组均为中文汉字,根据 font-size 设定子容器宽度,如果 buttonpadding 或者 margin ,可以加上对应的值。

回调函数/方法

// 计算子容器的宽度
const computeWidth = () => {
    let width = 0
    const btns = document.querySelectorAll(".radiobtn")
    btns.forEach(btn => {
        width += btn.offsetWidth
    })
    return width
}

// 处理左右移动
const handleMove = (e) => {
    console.log(subcon)
    // 容器的偏移量
    const offsetLeft = Number(subcon?.style?.left.slice(0, -2))
    // 左右箭头
    const leftArrow = document.querySelector('#left')
    const rightArrow = document.querySelector('#right')
    if (e.target.id === 'left') {
        // 点击左箭头,向右移动,控制左箭头的隐藏和右箭头的显示
        subcon.style.left = (offsetLeft + fatherwidth) + 'px'
        if (Number(subcon.style.left.slice(0, -2)) >= 0) {
            leftArrow.style.display = 'none'
            if (subWidth > fatherwidth) {
                rightArrow.style.display = 'block'
            }
        } else {
            rightArrow.style.display = 'block'
        }
        
    } else {
        // 控制右箭头的隐藏和左箭头的显示
        subcon.style.left = (offsetLeft - fatherwidth) + 'px'
        if (offsetLeft - fatherwidth <= 0) {
            leftArrow.style.display = 'block'
        }
        if ( offsetLeft + 2 * fatherwidth >= subWidth) {
            rightArrow.style.display = 'none'
        }
    }
  }

觉得有用可以点赞收藏哦~

tips: 本人代码更偏向hooks~

完整代码在github:github.com/gmx-white/s…