0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【実務で使えるSVG】CSSでできるSVGアニメーション チートシート

0
Posted at

🎯 やりたかったことは?

SVGを扱っていると、

「マウスを乗せたときに色を変えたい」
「線が描かれていくように見せたい」
「アイコンを回転させたい」

といった動きを付けたくなることがあります。

JavaScriptを使わなくても、単純なアニメーションであればCSSだけで実装できます。

ただ、transform-originstroke-dashoffset などは、久しぶりに使うと毎回少し迷います。

そこで、SVGでよく使うCSSアニメーションをチートシートとしてまとめておきます。


🚀 急いでいる人向け

やりたいこと 主に使うもの
色を滑らかに変える transition / fill / stroke
フェードイン・アウト opacity
点滅させる @keyframes / opacity
回転させる transform: rotate()
拡大・縮小する transform: scale()
線を描いているように見せる stroke-dasharray / stroke-dashoffset
アニメーション後の状態を維持する animation-fill-mode: forwards
繰り返す animation-iteration-count: infinite
一時停止する animation-play-state: paused

線を描いているように見せる場合は、次の形を覚えておくと使いやすいです。

<path
    class="draw-line"
    pathLength="100"
    d="M20 80 C80 10 140 150 220 50"
    fill="none"
    stroke="#333"
    stroke-width="4" />
.draw-line {
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    animation: draw 1.5s ease forwards;
}

@keyframes draw {
    to {
        stroke-dashoffset: 0;
    }
}

💡 この記事で分かること

  • SVGの色をCSSで滑らかに変える方法
  • 点滅・フェード・回転・拡大縮小の実装方法
  • 線を描いているように見せる方法
  • SVGで transform-origin を指定するときの注意点
  • クラスを切り替えてアニメーションを開始する方法
  • 動きを減らしたいユーザーへの配慮

CSSでSVGの色を変える

まずは、マウスを乗せたときに色を変える例です。

<svg
    width="160"
    height="100"
    viewBox="0 0 160 100"
    xmlns="http://www.w3.org/2000/svg">

    <rect
        class="color-change"
        x="20"
        y="20"
        width="120"
        height="60"
        rx="8" />

</svg>
.color-change {
    fill: #e5e7eb;
    stroke: #333;
    stroke-width: 2;
    transition:
        fill 0.2s ease,
        stroke 0.2s ease;
}

.color-change:hover {
    fill: #4caf50;
    stroke: #1b5e20;
}

transition を指定しておくと、色が一瞬で切り替わらず、滑らかに変化します。


opacity でフェードさせる

表示・非表示を滑らかに切り替える場合は、opacity が使いやすいです。

<circle
    class="fade-circle"
    cx="50"
    cy="50"
    r="35" />
.fade-circle {
    fill: #2196f3;
    opacity: 0.3;
    transition: opacity 0.3s ease;
}

.fade-circle:hover {
    opacity: 1;
}

opacity は要素全体に適用されます。

塗りだけを変えたい場合は fill-opacity、線だけなら stroke-opacity も使えます。


点滅させる

@keyframes を使うと、一定間隔で点滅させられます。

<circle
    class="blink-circle"
    cx="50"
    cy="50"
    r="30" />
.blink-circle {
    fill: #f44336;
    animation: blink 1s ease-in-out infinite;
}

@keyframes blink {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.2;
    }
}

infinite を指定しているため、アニメーションは繰り返されます。

一度だけ実行したい場合は infinite を外します。


SVG要素を回転させる

SVG要素を回転させるときは、transform-origin だけでなく transform-box も指定しておくと扱いやすいです。

<rect
    class="rotate-shape"
    x="30"
    y="30"
    width="60"
    height="60"
    rx="8" />
.rotate-shape {
    fill: #ff9800;

    transform-box: fill-box;
    transform-origin: center;

    animation: rotate 1.5s linear infinite;
}

@keyframes rotate {
    to {
        transform: rotate(360deg);
    }
}
transform-box: fill-box;
transform-origin: center;

を指定することで、対象要素の中央を基準に回転させています。

これがないと、想定していない位置を中心に回転することがあります。


拡大・縮小する

回転と同じように、transform-boxtransform-origin を指定します。

<circle
    class="pulse-circle"
    cx="50"
    cy="50"
    r="25" />
.pulse-circle {
    fill: #9c27b0;

    transform-box: fill-box;
    transform-origin: center;

    animation: pulse 1s ease-in-out infinite;
}

@keyframes pulse {
    0%,
    100% {
        transform: scale(1);
    }

    50% {
        transform: scale(1.25);
    }
}

このような拡大・縮小は、選択中の要素や通知アイコンを目立たせたい場合に使えます。


線を描いているように見せる

SVGでよく使われるのが、stroke-dasharraystroke-dashoffset を使ったアニメーションです。

<svg
    width="260"
    height="160"
    viewBox="0 0 260 160"
    xmlns="http://www.w3.org/2000/svg">

    <path
        class="draw-line"
        pathLength="100"
        d="M20 80 C80 10 140 150 220 50"
        fill="none"
        stroke="#333"
        stroke-width="4"
        stroke-linecap="round" />

</svg>
.draw-line {
    stroke-dasharray: 100;
    stroke-dashoffset: 100;

    animation: draw 1.5s ease forwards;
}

@keyframes draw {
    to {
        stroke-dashoffset: 0;
    }
}

最初は線全体をずらして見えない状態にしておき、stroke-dashoffset0 に戻しています。

stroke-dashoffset: 100
→ 線が見えない

stroke-dashoffset: 0
→ 線全体が見える

pathLength="100" を付ける理由

実際のpathの長さは、図形によって異なります。

pathLength="100"

を付けると、この記事の例では長さを 100 として扱えるため、CSS側の値を揃えやすくなります。

pathLength を付けない場合は、pathの長さに合わせて stroke-dasharraystroke-dashoffset を調整します。


塗りつぶしを後から表示する

線を描いたあとに塗りつぶしを表示することもできます。

<path
    class="draw-and-fill"
    pathLength="100"
    d="M100 20 L180 140 L20 140 Z"
    stroke="#333"
    stroke-width="4" />
.draw-and-fill {
    fill: transparent;

    stroke-dasharray: 100;
    stroke-dashoffset: 100;

    animation:
        draw 1.5s ease forwards,
        fill-shape 0.5s ease 1.5s forwards;
}

@keyframes draw {
    to {
        stroke-dashoffset: 0;
    }
}

@keyframes fill-shape {
    to {
        fill: #4caf50;
    }
}

2つ目のアニメーションに、

1.5s

の遅延を付けて、線の描画後に塗りを表示しています。


クラスを付けたときだけ動かす

画面表示と同時ではなく、処理成功時や選択時に動かしたい場合は、クラスを切り替える形が扱いやすいです。

<circle
    class="status-circle"
    cx="50"
    cy="50"
    r="30" />
.status-circle {
    fill: #4caf50;
    opacity: 0;
    transform: scale(0.8);

    transform-box: fill-box;
    transform-origin: center;
}

.status-circle.is-visible {
    animation: show-status 0.3s ease forwards;
}

@keyframes show-status {
    to {
        opacity: 1;
        transform: scale(1);
    }
}

JavaScript側では、必要なタイミングでクラスを追加します。

const statusCircle =
    document.querySelector(".status-circle");

statusCircle.classList.add("is-visible");

JavaScriptで細かい値を直接変更するより、見た目はCSSクラス側へまとめる方が管理しやすい場合があります。


アニメーションを一時停止する

.animated-shape {
    animation-play-state: running;
}

.animated-shape.is-paused {
    animation-play-state: paused;
}

クラスの追加・削除で一時停止できます。

element.classList.toggle("is-paused");

⚠️ ハマりやすいポイント

回転の中心がずれる

SVG要素へそのまま、

transform: rotate(360deg);

を指定すると、回転の中心が想定と違うことがあります。

まずは、

transform-box: fill-box;
transform-origin: center;

を確認します。


display:none から滑らかに表示できない

displayopacity のように中間状態を持たないため、滑らかなフェードには向きません。

フェードさせたい場合は、

opacity: 0;
visibility: hidden;

から、

opacity: 1;
visibility: visible;

へ切り替える方法が使えます。


線の描画には stroke が必要

stroke-dasharraystroke-dashoffset は線に対して使うため、対象要素へ stroke を指定します。

fill="none"
stroke="#333"

のようにしておくと分かりやすいです。


transformを複数のアニメーションで上書きしない

例えば回転と拡大縮小の両方で、

transform: rotate(...);
transform: scale(...);

を別々に指定すると、後から適用された方で上書きされることがあります。

同時に使う場合は、

transform: rotate(180deg) scale(1.2);

のようにまとめるか、親子要素に分けて適用します。


動きを減らす設定にも対応する

ユーザーのOS設定でアニメーションを減らしている場合は、動きを停止できます。

@media (prefers-reduced-motion: reduce) {
    .blink-circle,
    .rotate-shape,
    .pulse-circle,
    .draw-line {
        animation: none;
        transition: none;
    }
}

装飾目的のアニメーションなら、無効化しても操作に影響しない作りにしておくと安全です。


📝 まとめ

SVGのCSSアニメーションでは、まず次を覚えておけば大体対応できます。

動き 主な指定
色変更 transition / fill / stroke
フェード opacity
点滅 @keyframes
回転 rotate()
拡大縮小 scale()
線の描画 stroke-dasharray / stroke-dashoffset
状態による開始 クラスの追加・削除

自分の場合、特に忘れやすいのは、

transform-box
transform-origin
stroke-dasharray
stroke-dashoffset

あたりです。

SVGの動きで迷ったときに見返せるよう、ひと通りまとめておきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?