今回はp5jsのトレーニングとして、arc
と簡単なEaseOut関数を使ったコードを作りました。
このコードの要点のみ解説したいと思います。
最終的なコードはCodepenでご確認いただけます。
一見複雑にみえますが、主な描画関数はarc
です。
noFill(); // 塗りつぶしをなくします。
stroke(線の色);
strokeWeight(線の太さ);
arc(円弧の中心x座標, 円弧の中心y座標, 円弧の幅, 円弧の高さ, 円弧の開始角度, 円弧の終了角度);
円弧の定義の内、動的に変えたい値を1つのオブジェクトに格納します。
動的に変えたいのは色、太さ、円弧の大きさ、円弧の長さです。
自動で様々な円弧を生成したいので、値の初期値にrandom関数を使い、オブジェクトを定義します。
{
color: color(random(255), random(255), random(255)), // 線の色
weight: random(1, 3), // 先の太さ
arcWidth: random(50, width), // 円弧の幅と高さ、正円は幅と高さも同じなので幅のみ定義
startDegree: random(360), // 円弧の開始角度
arcLength: radians(random(30, 120)), // 円弧の長さを角度で定義、開始角度とると円弧の終了角度になる
}
for文を使い、好きな数の円弧の定義を生成し、arcs
に格納します。
let arcs = [];
for(let i = 0; i < 30; i++) {
arcs.push({
color: color(random(255), random(255), random(255)),
weight: random(1, 3),
arcWidth: random(50, width),
startDegree: random(360),
arcLength: radians(random(30, 120)),
})
}
Easing[イージング]に関しては、CodeGridさんの記事で詳しく解説されているのでわからない方はざっと見たほうがいいかもしれません。
ここでは、Processing内でサクッと書きたかったので、 こちらの記事の式が簡単だったので、引用させていただきました。
nowValue += (tagetValue - nowValue) * 0.05;
要は目的の値までの距離を均等に徐々に足していくという式です。
目的の値に近づくほど足す値が小さくなっていくので、EaseOut[イーズアウト]の形になります。
他にも、Robert Pennerさんのeasing関数など、様々なEasing関数があるようです。後日チャレンジしてみたいと思います。
そして、Easingの値を格納するために、円弧の定義に新たにdelayDeg
を追加します。
円弧は0から360の角度で指定するので、目標角度を360としdelayFinalDeg
に格納します。
上記のEasing式に当てはめると以下の様なコードになります。
const delayFinalDeg = 360;
// Easing部分の式
delayDeg += (delayFinalDeg - delayDeg) * 0.05;
delayDeg
は円弧ごとに変えたいので、先ほどのオブジェクトに追加します。
{
color: color(random(255), random(255), random(255)),
weight: random(1, 3),
arcWidth: random(50, width),
startDegree: random(360),
arcLength: radians(random(30, 120)),
delayDeg: random(360), // この行を追加
}
最後に、p5jsのdraw関数内でcanvasの中心座標に円弧を描きます。
Easing値となるdelayDeg
は円弧の開始と終了座標にそれぞれ加算します。
arc(
width/2,
height/2,
arcWidth,
arcWidth,
radians(delayDeg + startDegree) - arcLength,
radians(delayDeg + startDegree),
);
delayDeg
が360まで到達(一回転する)したあと、再度ループして描画させたいので、360に近づいたタイミングで0に戻します。
今回使用したEasing式だと360に値に収束しますが、360になることはないので、-1
した値とdelayDeg
を比較させます。
if (delayDeg > delayFinalDeg - 1) arcLine.delayDeg = 0;