トレイルトップに戻る    印刷する

時系列のデータを図形の大きさで表すーDatamateを使って書く

ラーニングトレイル2の(2)時系列変化で、データの時系列変化を、図形の大きさで表しました。 この時、図形を描く位置やデータを切り替えるタイミング(アニメーションさせるスピード)は スケッチ内で計算しました。つまり、位置やアニメーションの指定を自分で書いたのですが、 Datamateライブラリ が提供する機能を使うと、その処理を個別に書かずに、Datamateに任せることができます。

Datamateライブラリを使うために、Datamate.jsファイルを参照できるように指定します。

年ごとに円の大きさを切り変える

年ごとに変化するデータを、図形の大きさで表した例であるリストT2-2-1をDatamate.jsの機能を使って書き換えてみます。

[1]視覚化の対象となるデータセットを作る

9年分の年、猫の数、犬の数のデータを次のようなテーブルと考えます。
"年""猫""犬"
"2013年"84098714
"2014年"84258200
"2015年"82977994
"2016年"83338008
"2017年"86727682
"2018年"88497616
"2019年"87647579
"2020年"86287341
"2021年"89467106
Datamateでは、この表の列がひとつのデータセットとして扱われ、次のように列のタイトルと値の配列を指定します。 列のタイトルがデータ名になります。
  Datamate.make('データ名', [データの配列]);
文字列は引用符で囲みます(二重"でも一重'でもいい)。このデータの場合、次のように3つのデータセットを作ります。
Datamate.make('年', ['2013年', '2014年', '2015年', '2016年', '2017年',
                     '2018年','2019年', '2020年', '2021年']);
Datamate.make('猫', [8409, 8425, 8297, 8333, 8672, 8849, 8764, 8628, 8946]);
Datamate.make('犬', [8714, 8200, 7994, 8008, 7682, 7616, 7579, 7341, 7106]);

[2]データを表示する領域を作る

表示のための領域(エリア)を、Datamate.makeArea()関数を使って作ります。
Datamate.makeArea(x座標, y座標, 横幅, 高さ, 列の分割数, 行の分割数);
表示領域のキャンバス内での(x,y)位置と、表示領域の幅と高さ、そしてその領域を何列に分けるか、何行に分けるかを指定します。 キャンバス全体を2列1行に分割するには次のように書きます。
Datamate.makeArea(0, 0, width, height, 2, 1);

[3]データ領域とデータを結びつける

Datamate.bindArea()関数あるいはDatamate.bindAreas()関数を使って、どのエリアにどのデータセットを表示するかを指定します。
Datamate.bindArea('データ名', 列位置, 行位置);
Datamate.bindAreas([データセット番号, データセット番号,..]);
猫と犬の2つのデータセットを順番に、表示エリアに結びつけるには、次のように書きます。
Datamate.bindAreas([1, 2]);
あるいは、データセットごとに、データ名と列、行の位置を指定して、次のように書くこともできます。
Datamate.bindArea('猫', 0, 0);
Datamate.bindArea('犬', 1, 0);

[4]データ領域の描画をする関数を定義する

この例では、データセットごとに次のような描画を行います。 これらの処理を関数としてまとめて定義しておきます。 関数として描画処理をまとめておくと、それをdraw()関数から呼び出すだけでよく、個々の描画処理をdraw()関数内で記述する必要がなくなります。
関数名は任意ですが、引数は表示するデータセットのインデックス(この例だと猫が0、犬が1)とします。
function drawData(index) {
	.....
}
drawData()関数内では、引数で渡されるインデックスのデータをDatamate.current()関数を使って取り出します。

[5]データ領域の中央の位置、大きさなどの情報を得る

描画処理を行う関数(上の[4]で定義したdrawData()関数)内で、 描画をする際には、データ領域の情報、例えば中央位置や幅、高さが必要になります。 Datamate.area()関数で、データセットと結びついた描画エリアの情報を得て、描画に使います。
Datamate.area('データ名'(またはデータセット番号));
例えば、drawData()関数内では、引数で渡されたインデックスを使って、次のように領域情報を得ます。
const area = Datamate.area(index);
Datamate.area()関数が返す値(areaオブジェクト)には、次のような変数に領域の情報が保存されています。 例えば、領域の中央に円を描くなら、次のように書きます。
ellipse(area.centerX, area.centerY, w, w);  //wは直径
 

[6]データを順に表示する(再生する)

データセット内のデータを順に表示することで、この例だと時系列のデータの変化をアニメーションとして描画できます。 これを実現するのが、Datamate.play()関数で、表示対象のデータを順番に動かします(これを再生と呼びます)。引数には、1秒間に何回データを動かす(次のデータを取り出す)のかを指定します。
Datamate.play(1秒間にデータを動かす回数);
例えば、引数に2を指定すると0.5秒ごとに、引数に0.4を指定すると2.5秒ごとに、Datamate.current()関数で取り出されるデータが順番に進みます。 再生しない(Datamate.play()関数を実行しない)場合、Datamate.current()関数で取り出されるデータは先頭のデータです。
リストT2-2-1では、スケッチが起動されてからの経過時間を計算して、3秒たったらデータを切り替えるといった処理を書いていましたが、データ切り替えの処理はDatamate.play()関数がするので、その記述は不要になります。

【リストT2-5-1】
const title = "猫と犬の飼育推計数";
const titleX = 120;  //この↑表題を表示するx座標
function setup() {
  createCanvas(450, 250);
  Datamate.make('年', ['2013年', '2014年', '2015年', '2016年', '2017年', '2018年',
	                                              '2019年', '2020年', '2021年']);
  Datamate.make('猫', [8409, 8425, 8297, 8333, 8672, 8849, 8764, 8628, 8946]);
  Datamate.make('犬', [8714, 8200, 7994, 8008, 7682, 7616, 7579, 7341, 7106]);
  Datamate.makeArea(0, 0, width, height, 2, 1);
  Datamate.bindAreas([1, 2]);
  Datamate.play(0.3);
  noStroke();
  textAlign(CENTER, CENTER);
}
function draw() {
  background(220);
  drawData(1);    // データ1を描画
  drawData(2);    // データ2を描画
}
function drawData(index) {
  const area = Datamate.area(index);    //割り当てられたエリアを取り出す
  const year = Datamate.current('年');  //データ名'年'からデータを取り出す
  const value = Datamate.current(area.name);  //結びついたデータセットからデータを取り出す
  const w = map(value, 7000, 9000, 30, 200);  //データを円の直径に換算
  fill(200, 0, 0);
  ellipse(area.centerX, area.centerY, w, w);
  fill(0);
  text(title+"("+year+")", titleX, 30);  //表題と年の表示
  fill(255);
  text(area.name + "\n" + value+ "千頭", area.centerX, area.centerY);
}

演習問題

【問題T2-5-1】
リストT2-5-1を変更し、円の大きさがスムーズに変化するようにしてみよう。
Datamate.jsライブラリの順次データを取り出すcurrent()関数は、今の値と次の値との間を補間(内挿)する機能を備えています。current()関数の第2引数にtrueを指定します。
Datamate.current(取り出すデータ名, true);
【リストT2-5-1】の例で説明すると、次のように書くと、play()関数で指定したフレームレートで順次データが代入されます。
const value = Datamate.current(area.name);
一方、第2引数にtrueを指定すると、
const vMove = Datamate.current(area.name, true);
vMoveには、今の値と次の値との間を補間した値が代入されます。これを使うと、円の大きさをスムーズに変化させることができます。

リストT2-2-2では、犬と猫の円の直径用に別々の変数を用意して、変化する円の直径を(自分で)計算していました。Datamate.jsを使って順次データを取り出していく場合は、この変化の計算をDatamate.current()の補間機能に任せるのが簡単です。

【問題T2-5-2】
問題T2-2-1を、Datamate.jsを使って書き直してみよう。 画像ファイルは、画像ページからコピーできます。
copyright © info