使用React,SVG和CSS设计一个分数计。
#css #网络开发人员 #react #svg

我最近致力于为Hyvor Blogs创建SEO分析仪,该博客需要一个分数表来显示SEO得分。这是关于我如何设计的简短指南。最终结果将看起来像:

Image description

我们将使用React,但是您可以在任何其他框架中轻松地使用相同的概念。反应部分非常微不足道。

Codepen上的完整代码

比分计的部分

这些是比分计的部分。我们将使用SVG作为进度栏。

Image description

ðâ€作为一个对SVG不太熟悉的人,我的第一个想法是仅使用CSS设计完整的组件。我尝试使用圆圈等几种不同的方式。但是,我无法获得完美的圆形边缘。所以,SVG!

来了

建立分数计

1.主组件

这是主要结构的样子。它需要一个道具:得分,这是0到100之间的数字。

export default function App({ score } : { score: number }) {

  return (
    <div className="score-wrap">
        <div className="score">
            <div className="score-bar">
                <div className="placeholder">{progressBar(100)}</div>
                <div className="score-circle">{progressBar(score, true)}</div>
            </div>
            <div className="score-value">
                <div className="score-name">Score</div>
                <div className="score-number">
                    {Math.round(score)}%
                </div>
            </div>
        </div>
    </div>
  );
}

2.进度栏SVG

现在,让我们设计进度栏组件,用于占位符和填充的SVG。

function progressBar(widthPerc: number, gradient: boolean = false) {
  const radius = 65;
  const dashArray = (Math.PI * radius * widthPerc) / 100;

  return (
    <svg width="200" height="120">
      <circle
        cx="100"
        cy="100"
        r={radius}
        fill="none"
        strokeWidth="25"
        strokeLinecap="round"
        strokeDashoffset={-1 * Math.PI * radius}
        strokeDasharray={`${dashArray} 10000`}
        stroke={gradient ? "url(#score-gradient)" : "#e5e5e5"}
      ></circle>
      {gradient && (
        <defs>
          <linearGradient id="score-gradient">
            <stop offset="0%" stopColor="red" />
            <stop offset="25%" stopColor="orange" />
            <stop offset="100%" stopColor="green" />
          </linearGradient>
        </defs>
      )}
    </svg>
  );
}

3. CSS

添加一些CSS以正确定位文本和进度条。

.score-wrap {
  display: flex;
  justify-content: center;
  margin-bottom: 20px;
}
.score {
  width: 200px;
  height: 120px;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.score-bar {
  position: absolute;
  width: 100%;
  height: 200%;
  border-radius: 50%;
  top: 0;
}
.score-bar .score-circle {
  position: absolute;
  top: 0;
}

.score-value {
  margin-bottom: 5px;
  text-align: center;
}
.score-name {
  color: #777;
}
.score-number {
  font-size: 25px;
  font-weight: 600;
}

进度栏SVG解释

我认为主组件和CSS零件是不言自明的。我将解释SVG如何逐步工作。

首先,在SVG画布中添加一个圆圈:

<svg width="200" height="120">
    <circle
        cx="100"
        cy="100"
        r="65"
    ></circle>
</svg>

Image description

然后,取下填充物并添加笔触。

<svg width="200" height="120">
    <circle
        cx="100"
        cy="100"
        r="65"
        fill="none"
        stroke-width="25"
        stroke="#e5e5e5"
    ></circle>
</svg>

Image description

然后,大多数魔术都是使用stroke-dasharraystroke-dashoffset完成的。

stroke-dasharray允许您定义破折号和间隙的图案。例如,如果添加了stroke-dasharray="20",您会看到类似的东西。

Image description

然后,添加stroke-linecap="round"给您漂亮的圆形破折号。

Image description

让我们进行一些计算以正确设置stroke-dasharray属性。在我们的React代码中,我们使用以下内容:

const dashArray = (Math.PI * radius * widthPerc) / 100;
// ...
strokeDasharray={`${dashArray} 10000`}

Math.PI * radius等于圆的圆周的一半。这就是我们对进度栏的占位符所需的(填充取决于当前的分数)。

注意:strokeDasharray中的10000是差距。因为,我们只需要一个破折号,所以我使用10000添加了一个巨大的差距,以确保仅绘制一个破折号。您可以将其设置为比âr。

更大的任何东西

所以,

Math.PI * radius
= 3.14 * 65
= 204.2

当我们将其添加到圆圈中时:

<svg width="200" height="120">
    <circle
        cx="100"
        cy="100"
        r="65"
        fill="none"
        stroke-width="25"
        stroke="#e5e5e5"
        stroke-dasharray="204.2 10000"
        stroke-linecap="round"
    ></circle>
</svg>

我们得到了:

Image description

最后,让我们使用stroke-dashoffset更改绘制第一个破折号的位置。在我们的React代码中,我们使用strokeDashoffset={-1 * Math.PI * radius}。所以,

-1 * Math.PI * radius
 = -3.14 * 65
 = -204.2

所以,我们的最终SVG代码看起来像这样:

<svg width="200" height="120">
    <circle
        cx="100"
        cy="100"
        r="65"
        fill="none"
        stroke-width="25"
        stroke="#e5e5e5"
        stroke-dasharray="204.2 10000"
        stroke-linecap="round"
        stroke-dashoffset="-204.2"
    ></circle>
</svg>

我们得到了我们需要的!

Image description

这是进度栏的占位符。在填充物中,我们使用梯度。两者都使用CSS彼此放置。

最后的想法

虽然比分表UI看起来很简单,但要正确创建它需要一些精力,尤其是如果您对SVG不太熟悉。我希望这篇文章能帮助您了解SVG圈子,破折号和差距。随时重复您的项目中的代码。

如前所述,我为Hyvor Blogs的SEO分析仪编写了此评分表,该分析仪在您撰写时分析了博客文章,并为您提供了实时的反馈。这篇文章的外观:

Image description

查看Hyvor Blogs及其提供的所有功能,以使博客变得非常简单。

如果您对文章有任何反馈,请随时在下面发表评论。