You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS中如何根据选中选项实现圆形边框进度填充

嘿,作为React新手遇到这种视觉交互问题太正常啦!我来帮你一步步实现这个圆形边框进度填充的效果,其实用SVG来做会非常直观,而且代码也不难理解~

首先,我们需要用React的状态来跟踪当前选中的选项,然后根据选中的选项计算进度比例,最后用SVG的圆形元素实现边框进度的动态变化。下面是完整的实现代码,我会一步步给你解释:

import { useState } from 'react';

function ProgressCircleTabs() {
  // 用状态跟踪当前激活的选项索引,默认0对应Head
  const [activeIndex, setActiveIndex] = useState(0);
  
  // 把四个选项存在数组里,方便循环渲染
  const tabs = [
    { label: 'Head(头部)' },
    { label: 'Body(主体)' },
    { label: 'Script(脚本)' },
    { label: 'End Note(尾注)' }
  ];

  // SVG圆形进度条的计算逻辑
  const circleRadius = 45;
  // 计算圆的周长,用于进度条的虚线偏移计算
  const circumference = 2 * Math.PI * circleRadius;
  // 根据当前激活的索引计算进度比例:0→25%,1→50%,以此类推
  const progressRatio = (activeIndex + 1) / tabs.length;
  // 通过偏移量控制红色边框显示的长度
  const strokeDashoffset = circumference * (1 - progressRatio);

  return (
    <div style={{ display: 'flex', gap: '2rem', alignItems: 'center', padding: '2rem' }}>
      {/* 选项列表区域 */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
        {tabs.map((tab, index) => (
          <button
            key={index}
            onClick={() => setActiveIndex(index)}
            style={{
              border: 'none',
              background: 'none',
              fontSize: '1rem',
              padding: '0.5rem',
              // 保留你之前实现的文本变色效果
              color: activeIndex === index ? 'red' : '#333',
              cursor: 'pointer',
              textAlign: 'left'
            }}
          >
            {index + 1}. {tab.label}
          </button>
        ))}
      </div>

      {/* SVG圆形进度条区域 */}
      <svg width="100" height="100" viewBox="0 0 100 100">
        {/* 灰色背景边框 */}
        <circle
          cx="50"
          cy="50"
          r={circleRadius}
          stroke="#e0e0e0"
          strokeWidth="4"
          fill="none"
        />
        {/* 红色进度边框 */}
        <circle
          cx="50"
          cy="50"
          r={circleRadius}
          stroke="red"
          strokeWidth="4"
          fill="none"
          // 把边框分成一个等于周长的虚线段
          strokeDasharray={circumference}
          // 通过偏移量控制显示的进度长度
          strokeDashoffset={strokeDashoffset}
          // 可选:让进度条两端更圆润
          strokeLinecap="round"
          // 旋转90度,让进度从顶部开始(默认从右侧开始)
          transform="rotate(-90 50 50)"
        />
      </svg>
    </div>
  );
}

export default ProgressCircleTabs;

关键部分解释:

  1. 状态管理:activeIndex用来记录当前选中的选项,点击按钮时更新这个状态,同时触发组件重新渲染。
  2. SVG进度计算:
    • circumference是圆的周长,这是实现边框进度的核心数值,用来设置strokeDasharray(把边框变成一个和周长等长的虚线)。
    • strokeDashoffset通过进度比例计算偏移量:进度越高,偏移量越小,红色边框显示的长度就越长。
    • transform="rotate(-90 50 50)"是为了让进度条从顶部开始,符合我们常规的视觉习惯,默认SVG圆形的起始点是右侧。
  3. 样式适配:你可以调整SVG的width/height和circleRadius来改变圆形的大小,修改strokeWidth调整边框的粗细,完全可以根据你的需求自定义样式。

这样就能实现你想要的效果:默认Head激活时圆形边框25%为红色,选中Body时50%,直到选中End Note时100%填充,同时保留你之前实现的文本变色效果~

内容的提问来源于stack exchange,提问作者Mohammed Sabir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:02:08