この記事は、「完走賞ゲットのため小ネタ 25記事を投稿しようとチャレンジ v2 Advent Calendar 2023」の 18日目の記事です。
今回の内容
今回の内容は、イージング関数チートシートの関数と、p5.js の lerp()・frameCount を組み合わせて、以下の動画のようなイージングを実装するというものです。
実装した内容
プログラムの内容
今回は、まずは実装したプログラムの紹介から始めてみます。
上で掲載した動画について、以下のようなお試し用の実装をしました。
function setup() {
createCanvas(600, 400);
fill(100, 150, 200);
}
function draw() {
background(20);
const t = (frameCount % 120) / 120;
x1 = lerp(20, width - 20, easing(t, 1));
x2 = lerp(20, width - 20, easing(t, 2));
circle(x1, height * 0.3, 60);
circle(x2, height * 0.7, 60);
}
function easing(t, num) {
// https://easings.net/ja#easeOutQuart
if (num === 1) return 1 - pow(1 - t, 4);
// https://easings.net/ja#easeInOutQuint
if (num === 2)
return t < 0.5 ? 16 * t * t * t * t * t : 1 - pow(-2 * t + 2, 5) / 2;
}
実装のポイントの部分は、主に以下の 2点です。
- 「easing()」という関数で、イージング処理用の関数を実装(イージング関数チートシートの内容を、少しだけ変えたもの)
- p5.js で標準で使える「lerp()」(https://p5js.org/reference/#/p5/lerp)を使って、上記のイージング処理用の関数を使った座標計算を行う
ざっくり書くと以上なのですが、それぞれ補足をしていきます。
実装に関する補足1
先に、「easing()」という関数についての補足を書きます。
この中では、以下の 3行目と 7行目のそれぞれでイージング用の計算を行っています。
引数の t は、0〜1 の値が入力され、それを 2つ実装したどちらかの関数で計算した値にして返します。
function easing(t, num) {
// https://easings.net/ja#easeOutQuart
if (num === 1) return 1 - pow(1 - t, 4);
// https://easings.net/ja#easeInOutQuint
if (num === 2)
return t < 0.5 ? 16 * t * t * t * t * t : 1 - pow(-2 * t + 2, 5) / 2;
}
2つの関数について、以下でさらに説明していきます。
「easeOutQuart」
1つ目の 1 - pow(1 - t, 4)
という処理のほうの話です。
これは、イージング関数チートシートのページでいうと、以下になります。
●イージング関数チートシート 「easeOutQuart」
https://easings.net/ja#easeOutQuart
このページを見ると 1 - Math.pow(1 - x, 4)
という処理で書かれています。
処理はそのままという感じで、違いは Math.pow() を p5.js で使える pow() にしたのと、変数名を変えたくらいです。
「easeInOutQuint」
次に t < 0.5 ? 16 * t * t * t * t * t : 1 - pow(-2 * t + 2, 5) / 2
と書いていた処理についてです。
これは、イージング関数チートシートのページでいうと、以下になります。
●イージング関数チートシート 「easeInOutQuint」
https://easings.net/ja#easeInOutQuint
ここで行った対応は、先ほどと同様です。
実装に関する補足2
次に、lerp() を使った部分の補足です。
具体的には、以下となります。
const t = (frameCount % 120) / 120;
x1 = lerp(20, width - 20, easing(t, 1));
まず、t を求める部分は p5.js で取得できる frameCount の数値から求めています。その値を、剰余演算を使って特定範囲内でのみ動くようにし、さらに 0〜1 の値になるようにしています。
それを lerp() の第三引数で使うのですが、上で書いたイージング処理用の関数を介して渡しています。これで、0〜1 を線形に動くのではなく、イージングが適用された変化をするようになります。
あとは、lerp() の第一引数と第二引数で、円の移動をする範囲の最小値・最大値を指定しています。これと、第三引数で求まる 0〜1 の値を組み合わせることで、イージングがかかった場合の x座標の値を算出することができます。
おわりに
今回扱ったイージングは、過去に例えば以下のライブラリを用いて扱ったことがあるものでした。
それを今回は、イージング関数チートシートの関数と p5.js の lerp() とを組み合わせて実装してみた形です。上記のライブラリを使ったほうが実装は容易になりますが、イージングの関数の中に手を入れたいときなどは、今回の方法を使うと良いかもしれません。
過去に書いたイージング関連の記事
以下は、イージング処理を含む内容を、過去に記事で書いたものです。