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

如何用SVG实现带圆角与末端垂线的半圆加载器?

半圆加载器问题解决方案

1. 为半圆线条添加圆角

SVG的<circle>元素支持strokeLinecap属性,将其设置为round即可让线条两端呈现圆角效果。需要同时给背景圆和进度圆添加该属性,保证整体视觉统一。

修改点:

  • 给两个<circle>标签添加strokeLinecap="round"

2. 在填充半圆末端添加垂线

需要计算进度末端的坐标,再绘制一条垂直线段。步骤如下:

  1. 计算已绘制弧长对应的弧度
  2. 根据弧度推导末端点的坐标
  3. 添加<line>元素绘制垂线,长度可设置为进度条的宽度(strokeWidth)

完整修改后的代码

React组件代码

function App() {
  return <SemiCircleProgress percentage={70} />;
}

function SemiCircleProgress({ percentage }) {
    const strokeWidth = 25;
    const background = "#D9D9D9";
    const diameter = 400;

    const coordinateForCircle = diameter / 2;
    const radius = (diameter - 2 * strokeWidth) / 2;
    const circumference = Math.PI * radius;
    const semiCirclePercentage = percentage * (circumference / 100);
    // 计算末端点坐标
    const drawnLength = circumference - semiCirclePercentage;
    const theta = drawnLength / radius;
    const endX = coordinateForCircle + radius * Math.cos(-theta);
    const endY = coordinateForCircle + radius * Math.sin(-theta);

    return (
        <div className="semicircle-container">
            <svg
                width={diameter}
                height={diameter / 2}
                style={{ transform: "rotateY(180deg)", overflow: "hidden" }}
            >
                <linearGradient id="gradient">
                    <stop offset="0%" stopColor="#B8F1C6" />
                    <stop offset="100%" stopColor="#EBF8A1" />
                </linearGradient>

                <circle
                    cx={coordinateForCircle}
                    cy={coordinateForCircle}
                    r={radius}
                    fill="none"
                    stroke={background}
                    strokeWidth={8}
                    strokeDasharray={circumference}
                    strokeLinecap="round"
                    style={{
                        strokeDashoffset: circumference
                    }}
                />
                <circle
                    cx={coordinateForCircle}
                    cy={coordinateForCircle}
                    r={radius}
                    fill="none"
                    stroke="url(#gradient)"
                    strokeWidth={strokeWidth}
                    strokeDasharray={circumference}
                    strokeLinecap="round"
                    style={{
                        strokeDashoffset: semiCirclePercentage,
                        transition:
                            "stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s"
                    }}
                />
                {/* 添加末端垂线 */}
                <line
                    x1={endX}
                    y1={endY}
                    x2={endX}
                    y2={endY + strokeWidth}
                    stroke="url(#gradient)"
                    strokeWidth={3}
                />
            </svg>
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));

CSS代码

body {
  background: #292929;
}

HTML代码

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

注:如果发现进度百分比显示反向(如设置70%却只显示30%),可将进度圆的strokeDashoffset改为circumference - semiCirclePercentage,这样百分比会和视觉进度一致。

内容的提问来源于stack exchange,提问作者0xSwego

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 20:05:17