p5.jsでバリアブルフォントをアニメーションさせる

この記事は、[Lancers（ランサーズ） Advent Calendar 2023](https://qiita.com/advent-calendar/2023/lancers) の12日目の記事です。

https://qiita.com/advent-calendar/2023/lancers

本記事では、p5.jsでバリアブルフォントを使って１文字ずつバラバラにアニメーションさせてみようという内容について紹介します。

こんにちは、普段はLancersでAndroidエンジニアをやっているのですが趣味でプロセッシング系も書いています。

## バリアブルフォントとは
バリアブルフォントは、文字の太さ(weight)や幅(width)などの軸を連続的に変化させることができます。これにより、フォントの表現力が飛躍的に向上し、微妙なニュアンスの調整や、ユーザーインタラクションに応じた動的なレスポンスが可能になります。

## Lancer of the Year 10th Anniversary

Lancersは12/16(土)にLancer of the Year(LOY)というイベントを開催します。

https://www.lancers.jp/award

このメインビジュアルにはバリアブルフォントが使われています。
LOYというイベントも10回目を迎え、フリーランスのインフラとして次の10年のビジョンをランサーの皆さんと一緒に創造し、ランサーズも自由自在に形を変えながら10年後を描いていきたいという思いが込められています。

参加の申し込みはこちらからできます。

https://peatix.com/event/3666632/

## 本編
というわけでお祝いも込めてバリアブルフォントを使ったモーショングラフィックを作ってみました。

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="qBgGJNZ" data-user="norihirosunada" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/norihirosunada/pen/qBgGJNZ">
  Untitled</a> by Norihiro Sunada (<a href="https://codepen.io/norihirosunada">@norihirosunada</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## p5.jsでバリアブルフォントを使うためにしたこと
### 使ったフォント
今回はGoogle FontsからWebフォントとして使えるArchivoを使いました。
htmlの`<head>`で読み込んで使いました。

https://fonts.google.com/specimen/Archivo

### p5.jsでフォントをアニメーションさせるために
p5.jsでバリアブルフォントをアニメーションさせるために、CSSのfont-variation-settingsプロパティを操作しました。
そして、1文字ずつ違うフォントスタイルを当てるために、それぞれの文字を`createGraphics`を使ってcanvasに割り当てました。

フォントスタイルの情報はクラス内で保持しています。
p5.jsにはフォントを扱うp5.Fontもありますが、バリアブルフォントを想定したスタイルの変更はないため、`style`と`drawingContext`を使って描画するときにCSSのスタイルを書き込んでいます。

ArchivoにはフォントサイズのほかにWeightとWidthの変数があります。
これらを`drawingContext`にフォントの情報、`font-variation-settings`に`"wght" {Weightの値}, "wdth" {Widthの値}`のように与えるとスタイルが当たります。

こちらがフォントスタイルを当てるコードです。
```javascript
// フォント設定
// 'font-variation-settings'をCSSプロパティで設定するための文字列準備
let fontSettings = `"wght" ${this.wght}, "wdth" ${this.wdth}`;
this.g.fill("white");

// CSSスタイルでフォントの変化を設定
this.g.drawingContext.font = `normal ${this.wght} ${this.fontSize}px "Archivo"`;
this.g.style("font-variation-settings", fontSettings);
```

こちらがコンストラクタも含めたクラスです。
```javascript
class VariableFontGraphic {
  constructor(x, y, width, height, char, fontSize, wght, wdth, parent) {
    this.g = createGraphics(width, height);
    this.x = x;
    this.y = y;
    this.char = char;
    this.fontSize = fontSize;
    this.wght = wght;
    this.wdth = wdth;
    
    this.g.textAlign(LEFT, BASELINE);
    this.g.textSize(this.fontSize);
    
    this.lerpAmount = {
      width: 0.05,
      height: 0.08
    }
    this.nextWidth = this.width
    this.nextHeight = this.height
    
    this.nextWdth = this.wdth
    this.nextWght = this.wght
    this.nextFontSize = this.fontSize
  }

  draw() {
    // 文字の描画処理
    // クリア
    this.g.clear();

    // フォント設定
    // 'font-variation-settings'をCSSプロパティで設定するための文字列準備
    let fontSettings = `"wght" ${this.wght}, "wdth" ${this.wdth}`;
    this.g.fill("white");
    
    // CSSスタイルでフォントの変化を設定
    this.g.drawingContext.font = `normal ${this.wght} ${this.fontSize}px "Archivo"`;
    this.g.style("font-variation-settings", fontSettings);
    // 文字を描画
    this.g.translate(0, this.height-10)
    this.g.text(this.char, 0, 0);

    // 描画されたグラフィックスをキャンバスに表示
    image(this.g, this.x, this.y-this.height/2);
    
    // canvasの大きさ最大までフォントを大きくする
    this.lerpFont()
  }
  
  //以下、省略
}

```

### 描画
先ほどのクラスを呼び出すとこのように描画されます。

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="dyaEaRv" data-user="norihirosunada" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/norihirosunada/pen/dyaEaRv">
  VariableFontMotionGraphic</a> by Norihiro Sunada (<a href="https://codepen.io/norihirosunada">@norihirosunada</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## アニメーション
無事バリアブルフォントを表示できたので、これのフォントサイズや太さ、幅、配置を変えてアニメーションさせたいのですが、これについては続きを別の記事で書こうと思います。

## 終わりに
バリアブルフォントを触ってみるとこんなにも自由に形を変えられるのかと驚きました。
CSSでアニメーションさせたり、動画の中で動かす情報は多かったのですが、JSから操作するものは少なかったので今回挑戦してみました。

フリーランスの日ということで12/16(土)にLancer of the Yearというイベントを開催します。
メインビジュアルに込められた思いやイベント自体の制作も面白いので興味が出た方は参加してくださるととても嬉しいです。