プログレスサークル

CSSのみテキスト

進捗率を示すサークルです。

実装のポイント

円周はSVGで作っています。仕組みとしてはテキストのアウトラインが浮かび上がるアニメーションと同様に破線をアニメーションさせています。インラインスタイルでCSS変数--progress: 0.8と入力することで任意の進捗率をアニメーションできます。

パスの長さはJavaScriptで動的に算出してもよいですが、作り方によっては事前に計算ができます。円周は直径×円周率で出せます。このとき線幅含めviewBoxの大きさぴったりで円のパスを描いていると直径 = viewBox - 線幅という数式が成り立ちます。

このコードではviewBox256 四方で作っていて、線幅が56pxなので直径は200pxになります。そこに円周率3.14159を掛けた値が円周になります。小数点を5桁くらいにしないと誤差が出るのでこれくらいの値をオススメします。

初期値は長さ分オフセットしておき、インラインスタイルで与えられた進捗率分をtransitionさせればアニメーションが完成です。

なお、レスポンシブに関してはSVG自体のwidthheightプロパティを変えてもstroke-dashoffsetなどの値を再計算する必要はありません。大雑把に言うと表示上は拡縮していても、計算上のパスの長さなどは変わっていないためです。

コード例

HTML

<svg
  width="256"
  height="256"
  viewBox="0 0 256 256"
  fill="none"
  xmlns="http://www.w3.org/2000/svg"
  class="progressCircle"
  style="--progress: 0.8"
>
  <path
    d="M128 28C183.228 28 228 72.7715 228 128C228 183.228 183.228 228 128 228C72.7715 228 28 183.228 28 128C28 72.7715 72.7715 28 128 28Z"
    stroke="#363636"
    stroke-width="56"
  />
</svg>

CSS

.progressCircle {
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --pi: 3.14159;
  --diameter: 200px; /* 円周パスの直径。直径はviewBoxきっちりで作った場合はviewBox幅(256px) - 線幅(56px)の太さになる */
  path {
    /* 円周パスの直径×円周率で算出できる。 */
    stroke-dasharray: calc(var(--diameter) * var(--pi));
    stroke-dashoffset: calc(var(--diameter) * var(--pi));
  }
  &.isActive {
    path {
      stroke-dashoffset: calc(
        var(--diameter) * var(--pi) * (1 - var(--progress))
      );
      transition: 1s stroke-dashoffset;
    }
  }
}
Copyright Web Motion Catalog all rights reserved.