時系列のデータを図形の大きさで表す
データの時系列変化を、図形の大きさで表してみよう。年ごとに円の大きさを切り変える
年ごとに変化するデータを、図形の大きさで表した例がリストT2-2-1です。ペットフード協会のデータに基づき、2013年から2021年までの猫と犬の飼育推計数の変化を円の直径を変えることで示しています。ただ数値で示すのではなく、アニメティックに円の大きさを変えることで、犬の飼育数が小さくなるのに対し、猫が増えているという変化の傾向を直感的に表現しています。
クリックで開始⇔停止
データは、[年、猫の数、犬の数]が一つのセットで、それが9年分あります。プログラムで扱いやすいように、年(dataName)、猫の数(dataCat)、犬の数(dataDog)を次のように別々の配列に入れておくことにします。dataName[8](つまり2021年)の猫の数はdataCat[8]、犬の数はdataDog[8]でアクセスできます。飼育数の単位は千頭です。
const dataName = ['2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']; const dataCat = [8409, 8425, 8297, 8333, 8672, 8849, 8764, 8628, 8946]; const dataDog = [8714, 8200, 7994, 8008, 7682, 7616, 7579, 7341, 7106];飼育数は大きな数値で、最小値7106から最大値8764の間(千頭単位)を変化します。値0から最大値を直接円の直径に比例換算すると、円の大きさの変化はわずかになり、ほとんどわかりません。そこで、数値7000から9000の変化に着目し、それを円の直径(30から200)に換算します。
catW = map(dataCat[n], 7000, 9000, 30, 200);dataCat[n]のnは今表示しようとしている年を表すインデックスで、0は2013年のデータ、1は2014年のデータです。
リストT2-2-1では、3秒ごとに各年のデータを切り替えています。draw()関数が実行されてから次に実行されるまでの時間が、p5.jsのシステム変数deltatimeにミリ秒単位で保存されています。このdeltatimeを使い、ある年のデータを表示してからの経過時間を加算しておいて、それが3000を超えたら次の年のデータを表示するようにしています(timingはdraw()関数の外で定義した変数、let timing = 0;)。
timing = timing + deltaTime; //timingにひとつの年を表示してからの経過時間を足し算していく if (timing > 3000) { n++; //表示するデータを次に進める if (n>=dataName.length) n=0; //最後まで表示したら先頭に戻る timing = 0; //経過時間をゼロに戻す }
【リストT2-2-1】 const catX = 120; //猫円の中心x座標 const dogX = catX + 200; //犬円の中心x座標 const cy = 140; //円の中心y座標 let timing = 0; let n = 0; //今表示しているデータのインデックス let catW = 0.0; //表示する猫円の直径 let dogW = 0.0; //表示する犬円の直径 const title = "猫と犬の飼育推計数"; const dataName = ['2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']; const dataCat = [8409, 8425, 8297, 8333, 8672, 8849, 8764, 8628, 8946]; const dataDog = [8714, 8200, 7994, 8008, 7682, 7616, 7579, 7341, 7106]; function setup() { createCanvas(450, 250); fill(0); textSize(14); noStroke(); textAlign(CENTER, CENTER); frameRate(10); } function draw() { background(240); timing = timing + deltaTime; if (timing > 3000) { n++; if (n>=dataName.length) n=0; timing = 0; } catW = map(dataCat[n], 7000, 9000, 30, 200); dogW = map(dataDog[n], 7000, 9000, 30, 200); fill(200, 0, 0); ellipse(catX, cy, catW, catW); ellipse(dogX, cy, dogW, dogW); fill(0); text(title+"("+dataName[n]+"年)", catX, 30); //データ名の表示 fill(255); text("猫", catX, cy); text("犬", dogX, cy); }
年ごとに円の大きさをスムーズに変化させる
リストT2-2-1は表示するデータが変わるタイミングで、新しい円の大きさに「ぱっ」と切り替わります。円の大きさの変化をスムーズにしたのが、下のスケッチです。クリックで開始⇔停止
新しい円の大きさ(targetCatWとtargetDogW)と今の大きさの差を一定の割合で、lerp関数を使って変化させています。2つの数値の間を直線的に補間する処理で、これをイージング(easing)と言います。関数lerp(今の値, 次の値, 割合)で、この計算をしてくれます。割合の値が小さいとゆっくり変化します。
const keisu = 0.1; // 割合を変数keisuに保存 catW = lerp(catW, targetCatW, keisu); //猫円の大きさ、targetCatWを目指して、keisu分ずつ変化そして、描く円の大きさを計算するところを、次のように変更します。
【リストT2-2-2】 //リストT2-2-1のdraw()関数の中、データを円の直径に換算の部分を変更 let targetCatW = map(dataCat[n], 7000, 9000, 30, 200); //猫飼育数に応じた円の大きさ let targetDogW = map(dataDog[n], 7000, 9000, 30, 200); //犬飼育数に応じた円の大きさ catW = lerp(catW, targetCatW, keisu); //猫円の大きさ、targetCatWを目指して、keisu分少しずつ変化 dogW = lerp(dogW, targetDogW, keisu); //犬円の大きさ、targetDogWを目指して、keisu分少しずつ変化 fill(200, 0, 0); ellipse(catX, cy, catW, catW); ellipse(dogX, cy, dogW, dogW); //以下リストT2-2-1と同じ }
演習問題
【問題T2-2-1】リストT2-2-1では、猫と犬の飼育推計数の変化を円の大きさで表しましたが、画像の大きさを変えることで、変化の傾向を示すアニメーションをするスケッチを作成してみよう。イージングを使って大きさがスムーズに変化するようにしてみよう。
それぞれ好みの画像を使ってください。下のスケッチで使っている画像ファイルは、画像ページからコピーできます。
クリックで開始⇔停止