SVGでGitHubのリポジトリリストにあるような折れ線グラフを描画

# はじめに

SVGを触ってみようとおもい、色々みている中で[polyline](https://developer.mozilla.org/ja/docs/Web/SVG/Element/polyline)というものを見つけました。指定したポイントを繋げ合わせる要素です。
これを見つけたとき、GitHubのリポジトリリストにある折れ線グラフを作成できるのでは？と思い、本記事の執筆に至った次第です。

![スクリーンショット 2023-06-10 15.30.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/c4ea9b1d-ba6d-667a-aabb-2db07217e730.png)

[misskey](https://github.com/misskey-dev/misskey)からスクショさせていただきました。

# MDNの例をもとに折れ線グラフを描画

まずはMDNの例を見ながら折れ線グラフを描画してみます。
指定したポイントを繋げ合わせる要素である[polyline](https://developer.mozilla.org/ja/docs/Web/SVG/Element/polyline)だけでまずはやってみましょう。

```html
<svg width="500" height="500">
    <polyline points="100,200 150,100 200,160 250,120 300,180" />
</svg>
```

![スクリーンショット 2023-06-10 15.41.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/15afacf8-2735-f3e0-cace-904a41ec6768.png)


あー。fillをnoneにしないといけないのですね。
`fill: none` にすると線もろとも消えてしまうので、[points#polyline](https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/points#polyline)を参考にstrokeをつけてみます。

```html
<svg width="500" height="500">
    <polyline
        points="100,200 150,100 200,160 250,120 300,180"
         fill="none"
        stroke="black"
    />
</svg>
```

![スクリーンショット 2023-06-10 15.45.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/5ee06e2e-1f94-f743-9d50-e04c68e99ff6.png)


できました。

# グラデーションをつけてみる

調べたらいい感じの例がありました。

- [stroke](https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/stroke)

[defs](https://developer.mozilla.org/ja/docs/Web/SVG/Element/defs)で線形グラデーションを定義する属性[linearGradient](https://developer.mozilla.org/ja/docs/Web/SVG/Element/linearGradient)を定義し、[stop](https://developer.mozilla.org/ja/docs/Web/SVG/Element/stop)でグラデーションの変わる位置と色を指定。
`stroke="url(#id)"`で `defs` で定義した属性を呼び出すわけですね。

```html
<svg width="500" height="500">
    <defs>
        <linearGradient id="myGradient">
            <stop offset="0%"   stop-color="blue" />
            <stop offset="100%" stop-color="red" />
        </linearGradient>
    </defs>
    <polyline
        points="100,200 150,100 200,160 250,120 300,180"
        fill="none"
        stroke="url(#myGradient)"
    />
</svg>
```

![スクリーンショット 2023-06-10 16.05.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/898fc8cc-3c7e-7dd5-b439-2944ba0a4be4.png)

いいね。
ただ、左右のグラデーションになっています。
今回やりたいのは上下のバリデーション。
ではどうすればいいのでしょうか？

# 上下のバリデーションにする

[SVGにおけるグラデーション](https://developer.mozilla.org/ja/docs/Web/SVG/Tutorial/Gradients)に書かれていました。

> `<linearGradient>` 要素は、他にもいくつかの属性を持ち、グラデーションの大きさや外観を指定します。
> グラデーションの方向は、`x1`, `x2`, `y1`, `y2`という属性で指定された 2 つの点によって制御されます。
> これらの属性は、グラデーションが移動する線を定義します。
> グラデーションのデフォルトは水平方向ですが、これらを変更することで回転させることができます。

`x1`, `y1`で0%(=0)側を、`x2`, `y2`で100%(=1)側のグラデーション方向・範囲を指定することができます。

- [グラデーションとパターン](https://triple-underscore.github.io/SVG11/pservers.html)

それを踏まえて修正します。

```html
<svg width="500" height="500">
    <defs>
        <linearGradient id="myGradient" x1="0" x2="0" y1="1" y2="0">
            <stop offset="0%" stop-color="blue" />
            <stop offset="100%" stop-color="red" />
        </linearGradient>
    </defs>
    <polyline
        points="100,200 150,100 200,160 250,120 300,180"
        fill="none"
        stroke="url(#myGradient)"
        stroke-width="2"
    />
</svg>
```

![スクリーンショット 2023-06-10 17.11.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/bbd09f53-9a4f-b65c-91f1-99d852489d79.png)

できてるぅ！

GitHubのページから色と閾値をパクってきて反映してみます。

```html
<svg width="500" height="500">
    <defs>
        <linearGradient id="myGradient" x1="0" x2="0" y1="1" y2="0">
            <stop offset="0%" stop-color="#9be9a8"></stop>
            <stop offset="10%" stop-color="#40c463"></stop>
            <stop offset="25%" stop-color="#30a14e"></stop>
            <stop offset="50%" stop-color="#216e39"></stop>
        </linearGradient>
    </defs>
    <polyline
        points="0,0 50,400 100,200 150,100 200,500 250,300 300,500"
        fill="none"
        stroke="url(#myGradient)"
        stroke-width="2"
    />
</svg>
```

![スクリーンショット 2023-06-10 17.17.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/bacd7c7c-e891-e767-0d51-1b7d9f2ca0d3.png)

当たり前ですが、x軸は左から右へ、y軸は上から下へと大きくなるので上下逆になってますね。

# 上下回転

`transform="translate(0, height) scale(1,-1)"` を用います。

[translate](https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/transform#translate) が移動、 [scale](https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/transform#scale)が拡大縮小操作です。
scaleのy軸を `-1倍` してやることで上下反転、そうすると位置も反転してしまうのでtranslateで移動してあげています。

```html
<defs>
    <linearGradient id="myGradient" x1="0" x2="0" y1="1" y2="0">
        <stop offset="0%" stop-color="#9be9a8"></stop>
        <stop offset="25%" stop-color="#40c463"></stop>
        <stop offset="50%" stop-color="#30a14e"></stop>
        <stop offset="75%" stop-color="#216e39"></stop>
    </linearGradient>
</defs>
<polyline
    points="0,0 50,400 100,200 150,100 200,500 250,300 300,500"
    fill="none"
    stroke="url(#myGradient)"
    stroke-width="2"
    transform="translate(0, 500) scale(1,-1)"
/>
```

![スクリーンショット 2023-06-10 17.38.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/ac6b34be-9b4c-f8f4-760f-e973eabc6b03.png)


ただこれだと画像の通り色も上下逆転してしまっているので、`y1=0 y2=1`としてやります。

```html
<defs>
    <linearGradient id="myGradient" x1="0" x2="0" y1="0" y2="1">
        <stop offset="0%" stop-color="#9be9a8"></stop>
        <stop offset="25%" stop-color="#40c463"></stop>
        <stop offset="50%" stop-color="#30a14e"></stop>
        <stop offset="75%" stop-color="#216e39"></stop>
    </linearGradient>
</defs>
<polyline
    points="0,0 50,400 100,200 150,100 200,500 250,300 300,500"
    fill="none"
    stroke="url(#myGradient)"
    stroke-width="2"
    transform="translate(0, 500) scale(1,-1)"
/>
```

![スクリーンショット 2023-06-10 17.40.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299962/4613237d-4408-98e2-989d-cdbb0a24c7f8.png)

また、 `polyline`に`transform`をつけるのではなく、`<g>`で囲ってもいいかもですね。

```html
<g transform="translate(0, 520) scale(1,-1)">
    <polyline
        points="0,0 50,400 100,200 150,100 200,500 250,300 300,500"
        fill="none"
        stroke="url(#myGradient)"
        stroke-width="2"
    />
</g>
``` 

完成です！　お疲れ様でした！

# おわりに

GitHubのリポジトリリストにある折れ線グラフをSVGで作成できました。
SVGの入門としてはちょうどよかったかと思います。
おわり。

# 参考

- [SVGの記述方法](https://qiita.com/takeshisakuma/items/777e3cb0a54ea7b1dbe7)
- [HTML SVG の基本的な使い方（SVG入門）](https://www.webdesignleaves.com/pr/html/svg_basic.html)