RustのwasmによるSVGアニメーションのロゴつくってみた
Section: Technology

この記事は 広島大学ITエンジニア Advent Calendar 2020の13日目です。

前回前々回に続いて、今日に至るまでデザインやメタ情報の追加など複数のサイトの変更をしました。 今回は、その中でロゴについて説明していこうと思います。

ロゴ作成

自分の場合ロゴのイメージは大体あったため、それを実現するための技術選定をするところから始めることにしました。

ロゴのイメージ

  • 赤、緑、青ベースの3つのシャボン玉みたいなものが重なっている
  • それぞれ透過付きのグラデーションである
  • アニメーションがほしい

技術

イメージを実現するための技術として、CSSアニメーション、SVG、Canvas/WebGlの三つをまず見つけました。

軽くそれぞれの特徴を挙げると以下のようになります。

  • CSSアニメーション : 単純な操作の際に、簡単に導入できる
  • SVG : CSSだけでは表現できない際に用いる。ベクター。XML。
  • Canvas/WebGl : 2D、3D両方扱える。

シャボン玉の部分は円に近い図形であるところから、SVGで操作しやすそうであると感じたため、SVGを用いることにしました。

開発

YewのComponentで値の管理をすることにしました。

デザイン

ロゴのSVGは、イメージのように3つの<path>を用いてそれぞれdattributeをいじってシャボン玉感を出します。 dattributeでは、8本の3次ベジェ曲線を用いて表現しています。2本の円弧で描画する方法もあるのですが、今回はシャボン玉感を出したいので多くのパラメータをいじれる8本の3次ベジェ曲線を用いました。

<SVG viewBox="0, 0, 250, 250" xmlns="http://www.w3.org/2000/SVG" aria-hidden="true">
    ...
    <path fill="url(#layer)" ref=self.node_ref.clone() />
</SVG>

グラデーションを出すために色々調べていたところ、<meshGradient>要素が幅広くグラデーションを表現できそうだと知ったので用いてみたら、残念ながら動作しませんでした。原因はwebでは対応してないからっぽいです。自分のイメージでは一応単色であったので<radialGradient>要素で代用することにしました。

<radialGradient id="layer" cx="0.5" cy="0.5" r="0.5" fx="0.5" fy="0.5" ref=self.node_ref.clone()>
    <stop offset="0%" stop-color="rgba(0, 0, 255, .3)" />
    <stop offset="30%" stop-color="rgba(0, 0, 255, .26)" />
    <stop offset="60%" stop-color="rgba(0, 0, 255, .2)" />
    <stop offset="100%" stop-color="rgba(0, 0, 255, .08)" />
</radialGradient>

アニメーション

requestAnimationFrame()でアニメーションを用いるとsetInterval()を使用した時と比べて、ブラウザが描画するタイミングにあわせてくれるので前者を選びました。

Yewにおいての実装方法は、YewのレポジトリにWebGlのサンプルがあり、そこでrequestAnimationFrame()を用いているので、そちらを参考にしました。

完成

<path><radialGradient>のパラメータを変えると面白い形ができたりしました。そのため一生終わる気がせず、アドベントカレンダーを出さないようになりかけたので、とりあえず今のところは完成ということにしました。

終わりに

SVGの仕様やアニメーションの方法などを調べるところから始めたため、多少時間がかかったのですが、色々なことができることがわかりました。皆さんもSVGやってみて損はないと思います。ぜひSVG職人になってみてください。

最後まで読んでくださり、ありがとうございました。