VizつくりまShow!2024の対戦相手Chasosoさんの対策をしてみていた~花火の炎色反応Vizの作り方解説
この記事について
12/6(金)、VizつくりまShow本戦がありました。本戦を控えた1週間までに実施した対策について書いています。
考えたこと
どうにか優勝出来ないかずっと考えていた。
自分の技術を磨いて対策するのも大切だが、ここで、対戦相手を見て対策出来ないかを考えた。
今回の出場者で明らかに激強なのがChasosoさん。
Chasosoさんの対策がどうにか出来ないか考える。
中でも今年Tableauコミュニティを震撼させたのが以下のダッシュボード
花火の炎色反応 - Flame Reaction of Fireworks
public.tableau.com
周期表をクリックすると…
まったく意味が分からない花火の打ち上げのアニメーションでTableauコミュニティがざわついた。
ここで自分は思いました。このVizを読み解いてChasosoさんとの対決に備えよう、と。
VizつくりまShowでは動くダッシュボードの問題が頻発している。このリバースエンジニアリングはきっと何かに役立つと信じて。
2023年決勝の問題
2021年決勝の問題
以下、花火の炎色反応ダッシュボードの原理の解明をしていく。
アニメーションの原理
書式設定に「アニメーション」の設定があります。
打ち上がりのワークシートのアニメーションを見ると5秒というかなりゆっくりなアニメーションが設定されているのが分かります。
ただこれだけでは打ちあがって花火が上がるかどうかというのが良くわかりません。
打ち上げのワークシートを見てみます。
なにやら色んなフィールドが入っているのが分かりますが、真っ白でなんのこっちゃわかりません。
軸を表示してみます。
軸の表示範囲が5~90で固定されていました。
軸の表示範囲の固定を外し、背景色を付けてみると・・・
打ち上げ花火のもとになるものをようやく見つけました!
なにも表示されてなかったのは軸で固定していた範囲から外れたところにいたからですね。
ダッシュボード上では、元素記号をクリックするとcountが1増える、という動きをします。
この状態でパラメーターを動かすと・・・
一番下の花火が5秒のアニメーションによりゆっくり場外である上まで動いていくという実装がされています。
同様に花火部分を見てみましょう。
花火は1/4で分割されているようです。
これも同様に軸の固定を外してみます。
ダッシュボード上で見えているのは右上の小さい塊で、場外にこれだけたくさんのパーツが存在していました。
この状態でアニメーションをうごかすと・・・?
ゆっくりゆっくり外側から火花が動いていき、最終的に右上の表示範囲で弾けるように見せています。
アニメーションの流れとしては
0~4.5秒で打ち上げ花火を動かす
4.5~5秒で花火が弾ける
となるように軸の表示範囲を調整することで花火が打ちあがってから弾ける、というアニメーションが実現できているのでした。
打ち上げ花火についてもう少し詳しく見てみましょう。
Yの計算フィールドを見てみましょう。
データの動きは以下のようになります。
countが1から2に移るとき、
ID0はy=100の位置から消える
ID1はy=0から100まで移動する(これが打ち上げ花火のように見えている)
ID2は何もないところからy=0に花火のもとが配置される
ID3はなにも消えたまま
これがID違いで繰り返し発生するため、アニメーションとして動かすことが出来ているようです。花火部分も同様かなと思います。
作成手順
1から花火Vizを作ってみます。
データの準備
データを3つ用意します。今回は簡単にやるためTableau Publicからダウンロードしたダッシュボードファイルをtwb形式で保存してデータをとりだします。
周期表用データ
基本的な情報としては周期表そのままですが、「補正あり」というカラムを別途用意しています。
周期 補正あり:ランタノイドとアクチノイドを周期表の下に配置するために、該当する元素に対して周期を+3しています。
族 補正あり:ランタノイドとアクチノイドを周期表の下に配置するとき、ランタンとアクチニウムが4族の位置から始まるように配置するケースがあります。それを再現するために該当する元素に対して族に+1しています。
打ち上げ用データ
花火用データ
1~4象限にIDが50個入ります。
ただ、X補正とY補正は使用していなさそうでした。
象限と名がついていますが、打ち上げ用データのIDみたいな感じで使用しているようです。ここでいう50個のIDは花火の火種一つ一つに使われています。
カスタム形状の準備
カスタム形状を準備します。
今回2つの形状を準備します。
花火の先端用のぼんやりとした円の画像と、周期表用の四角形のマークを用意します。
カラーパレットの準備
花火の色は選択された元素に応じて数字が投げられる形式にしています。
炎色反応の色のためにカラーパレットが用意されています。色が連続型になっていないと上手く作動しないとのこと。
以下のパレットをpreference.tpsに登録します。
<color-palette custom='true' name='FlameReaction' type='ordered-sequential'>
<color>#22217b</color>
<color>#e2973b</color>
<color>#00ff00</color>
<color>#4d2de3</color>
<color>#00ff7f</color>
<color>#e6e6fa</color>
<color>#2ec2a4</color>
<color>#3873ff</color>
<color>#9370db</color>
<color>#dc143c</color>
<color>#dc143c</color>
<color>#adff2f</color>
<color>#ffff00</color>
<color>#873e7f</color>
</color-palette>
周期表の作成
計算フィールド「POINT」を作成。
これが各元素の位置になります。
MAKEPOINT(-[周期 補正あり],[族 補正あり])
「POINT」を詳細に配置する。そうすると各元素が地図上に配置されます。
マップを「なし」に設定する。これで地図は見えなくなります。
詳細に「原子番号」を配置。
マークを形状に変更。グレーの四角の形状に設定する。
計算フィールド「元素記号(Label)」を作成。ランタノイド、アクチノイドが入る箇所を空白にするために設定。
IF [元素記号] IN ("-1","-2")
THEN ""
ELSE [元素記号]
END
「元素記号(Label)」をラベルに配置。サイズや配置などを調整する。
パラメーター「count」を作成。整数型で初期値を1に設定。
計算フィールド「count+1」を作成し、ディメンションとして詳細に配置する。
パラメーターアクションに設定することで、クリックするたびにパラメーター「count」の数を1増やすことが出来る。
[count]+1
計算フィールド「FALSE」「TRUE」を作成し詳細に配置する。
これをフィルターアクションで使用することで、周期表を連続でクリックすることが出来る。
FALSE
TRUE
計算フィールド「元素(En) (Label)」の作成。ツールヒントに元素の英語表記を表示するのに使用。ランタノイドとアクチノイドの例外処理つき。
IF [元素(En)] IN ("-1","-2")
THEN ""
ELSE " ("+[元素(En)]+")"
END
計算フィールド「元素(Jp) (Label)」の作成。ツールヒントの表記用。ランタノイドとアクチノイドの例外処理つき。
IF [元素(Jp)] IN ("-1","-2")
THEN ""
ELSE " | "+[元素(Jp)]
END
「元素(En)」「元素(Jp)」「元素(En) (Label)」「元素(Jp) (Label)」を詳細に配置する。
計算フィールド「炎色反応あり」を作成。
炎色反応が設定されているかどうかを判定。
NOT ISNULL([元素記号 (炎色反応.csv)])
計算フィールド「色(Label)」を作成。こちらもツールヒント用。
IF [炎色反応あり]
THEN "炎色反応 : "+[色]
ELSE ""
END
「色(Label)」「炎色反応あり」を詳細に配置。
パラメーター「選択記号」を作成。データ型を文字列に設定し現在の値を「Li」に設定。
計算フィールド「選択中」を作成。選択した元素に色を付けるのに使用。
[選択記号]=[元素記号]
計算フィールド「選択中」を色に配置。
詳細に配置した「炎色反応あり」を、配置したまま詳細から色に変更。これにより、2つのフィールドから色の設定をすることが可能。
色を調整。これで周期表は完成。
打ち上げワークシートの作成
打ち上げのデータを使用して新規ワークシート作成。
計算フィールド「Y」を作成。
アニメーションので開設した通り、クリックしてcountが1増えるのに応じて各行で打ちあげ花火のオブジェクトが切り替わるようにCASE文で設定している。
CASE [Id]
WHEN 0 THEN
CASE [count]%4
WHEN 0 THEN 0
WHEN 1 THEN 100
WHEN 2 THEN null
WHEN 3 THEN null
END
WHEN 1 THEN
CASE [count]%4
WHEN 0 THEN null
WHEN 1 THEN 0
WHEN 2 THEN 100
WHEN 3 THEN null
END
WHEN 2 THEN
CASE [count]%4
WHEN 0 THEN null
WHEN 1 THEN null
WHEN 2 THEN 0
WHEN 3 THEN 100
END
WHEN 3 THEN
CASE [count]%4
WHEN 0 THEN 100
WHEN 1 THEN null
WHEN 2 THEN null
WHEN 3 THEN 0
END
END
計算フィールド「Y-5」を作成。打ち上げ花火の線の部分を表現するために花火の位置から‐5している。
[Y]-5
行にY,メジャーバリューを配置し、二重軸に設定。メジャーバリューをY-5,Yの2つに設定。
Yのマークの設定。サイズにY,詳細にIdを追加。サイズは反転させる。
メジャーバリューのマークの設定。マークを線に設定。
メジャーネームをサイズに、Idとメジャーネームをこの順番で詳細に、メジャーバリューをパスに配置。
二重軸の軸の同期を設定。
countを1増やすと高速でマークが上に上がるのが分かる。
両方のマークを白に設定する。
メジャーバリューの線の方だけ不透明度を50%に設定する。
軸の範囲を5~90に設定。
ヘッダーや枠線、グリッド線などを非表示する。
書式設定→アニメーションでシートごとの設定の方について、期間を5秒に設定。
一時的にワークシートの網掛けをつけ、countを1つ増やしてみて、下から上にオブジェクトが正しく移動することを確認する。
花火ワークシートの作成
ワークシートを作成し、花火のデータを使用する。
計算フィールド「X_1」を作成。
//一番外側の20個の位置を設定
IF [Id]<= 20
THEN SIN(PI()*([Id]-1)/38)
//2番目に外側の14個の位置を設定。内側に位置させるために0.75倍している。
ELSEIF [Id]<= 34
THEN SIN(PI()*([Id]-21)/26)*0.75
//3番目に外側の8個の位置を設定。内側に位置させるために0.5倍している。
ELSEIF [Id]<= 42
THEN SIN(PI()*([Id]-35)/14)*0.5
//一番内側の8個の位置を設定。内側に位置させるために0.25倍している。
ELSE SIN(PI()*([Id]-43)/14)*0.25
END
同様の考え方で「Y_1」も作成。SINをCOSにするだけ。
IF [Id]<= 20
THEN COS(PI()*([Id]-1)/38)
ELSEIF [Id]<= 34
THEN COS(PI()*([Id]-21)/26)*0.75
ELSEIF [Id]<= 42
THEN COS(PI()*([Id]-35)/14)*0.5
ELSE COS(PI()*([Id]-43)/14)*0.25
END
計算フィールド「POINT_1」を作成。
打ち上げでいうIDが花火でいうところの象限になる。始点を最終的に花火が表示されるところから10倍逆方向に離れた場所に設定するために‐10倍している。
CASE [象限]
WHEN 1 THEN
MAKEPOINT(
CASE [count]%4
WHEN 0 THEN [Y_1]*-10
WHEN 1 THEN [Y_1]*1
WHEN 2 THEN null
WHEN 3 THEN null
END
,
CASE [count]%4
WHEN 0 THEN [X_1]*-10
WHEN 1 THEN [X_1]*1
WHEN 2 THEN [X_1]*1
WHEN 3 THEN [X_1]*-10
END
)
WHEN 2 THEN
MAKEPOINT(
CASE [count]%4
WHEN 1 THEN [Y_1]*-10
WHEN 2 THEN [Y_1]*1
WHEN 3 THEN null
WHEN 0 THEN null
END
,
CASE [count]%4
WHEN 1 THEN [X_1]*-10
WHEN 2 THEN [X_1]*1
WHEN 3 THEN [X_1]*1
WHEN 0 THEN [X_1]*-10
END
)
WHEN 3 THEN
MAKEPOINT(
CASE [count]%4
WHEN 2 THEN [Y_1]*-10
WHEN 3 THEN [Y_1]*1
WHEN 0 THEN null
WHEN 1 THEN null
END
,
CASE [count]%4
WHEN 2 THEN [X_1]*-10
WHEN 3 THEN [X_1]*1
WHEN 0 THEN [X_1]*1
WHEN 1 THEN [X_1]*-10
END
)
WHEN 4 THEN
MAKEPOINT(
CASE [count]%4
WHEN 3 THEN [Y_1]*-10
WHEN 0 THEN [Y_1]*1
WHEN 1 THEN null
WHEN 2 THEN null
END
,
CASE [count]%4
WHEN 3 THEN [X_1]*-10
WHEN 0 THEN [X_1]*1
WHEN 1 THEN [X_1]*1
WHEN 2 THEN [X_1]*-10
END
)
END
POINT_1を詳細に配置する。
IDと象限を詳細に配置する。
マークを円に配置する。countを1増やすと右上に丸が移動するのがわかる。この動きが花火のもとになる。
マークレイヤーの追加からPOINT_1を追加する。
新たに配置したPOINT_1のマークを形状に設定し、ID,象限を詳細に配置する。
マークを追加したふわふわの形状に設定。
ここから花火の放射状の線の形の作成。
計算フィールド「Line_X_(+)-1」の作成
IDが25以下を始点、26以上を終点にしている。2行目のELSE以降で終点の位置を設定している。1象限にIDが50しかないので、半分半分で用途を分けている。
IF [Id]<=25 THEN [X_1]
ELSE
IF [Id]-25<= 20
THEN SIN(PI()*([Id]-1-25)/38)
ELSEIF [Id]-25<= 34
THEN SIN(PI()*([Id]-21-25)/26)*0.75
ELSEIF [Id]-25<= 42
THEN SIN(PI()*([Id]-35-25)/14)*0.5
ELSE SIN(PI()*([Id]-43-25)/14)*0.25
END*0.5
END
同様に計算フィールド「Line_Y_(+)-1」の作成
IF [Id]<=25 THEN [Y_1]
ELSE
IF [Id]-25<= 20
THEN COS(PI()*([Id]-1-25)/38)
ELSEIF [Id]-25<= 34
THEN COS(PI()*([Id]-21-25)/26)*0.75
ELSEIF [Id]-25<= 42
THEN COS(PI()*([Id]-35-25)/14)*0.5
ELSE COS(PI()*([Id]-43-25)/14)*0.25
END*0.5
END
続いて、計算フィールド「Line_X_(+)-2」の作成
今度は26以上を始点、25以下を終点に役割を分けている。
IF [Id]>25 THEN [X_1]
ELSE
IF [Id]+25<= 20
THEN SIN(PI()*([Id]-1+25)/38)
ELSEIF [Id]+25<= 34
THEN SIN(PI()*([Id]-21+25)/26)*0.75
ELSEIF [Id]+25<= 42
THEN SIN(PI()*([Id]-35+25)/14)*0.5
ELSE SIN(PI()*([Id]-43+25)/14)*0.25
END*0.5
END
同様に計算フィールド「Line_Y_(+)-2」の作成
IF [Id]>25 THEN [Y_1]
ELSE
IF [Id]+25<= 20
THEN COS(PI()*([Id]-1+25)/38)
ELSEIF [Id]+25<= 34
THEN COS(PI()*([Id]-21+25)/26)*0.75
ELSEIF [Id]+25<= 42
THEN COS(PI()*([Id]-35+25)/14)*0.5
ELSE COS(PI()*([Id]-43+25)/14)*0.25
END*0.5
END
計算フィールド「POINT_1-1 (line)」の作成
CASE [象限]
WHEN 1 THEN
MAKEPOINT(
CASE [count]%4
WHEN 0 THEN [Line_Y_(+)-1]*-10
WHEN 1 THEN [Line_Y_(+)-1]*1
WHEN 2 THEN null
WHEN 3 THEN null
END
,
CASE [count]%4
WHEN 0 THEN [Line_X_(+)-1]*-10
WHEN 1 THEN [Line_X_(+)-1]*1
WHEN 2 THEN [Line_X_(+)-1]*1
WHEN 3 THEN [Line_X_(+)-1]*-10
END
)
WHEN 2 THEN
MAKEPOINT(
CASE [count]%4
WHEN 1 THEN [Line_Y_(+)-1]*-10
WHEN 2 THEN [Line_Y_(+)-1]*1
WHEN 3 THEN null
WHEN 0 THEN null
END
,
CASE [count]%4
WHEN 1 THEN [Line_X_(+)-1]*-10
WHEN 2 THEN [Line_X_(+)-1]*1
WHEN 3 THEN [Line_X_(+)-1]*1
WHEN 0 THEN [Line_X_(+)-1]*-10
END
)
WHEN 3 THEN
MAKEPOINT(
CASE [count]%4
WHEN 2 THEN [Line_Y_(+)-1]*-10
WHEN 3 THEN [Line_Y_(+)-1]*1
WHEN 0 THEN null
WHEN 1 THEN null
END
,
CASE [count]%4
WHEN 2 THEN [Line_X_(+)-1]*-10
WHEN 3 THEN [Line_X_(+)-1]*1
WHEN 0 THEN [Line_X_(+)-1]*1
WHEN 1 THEN [Line_X_(+)-1]*-10
END
)
WHEN 4 THEN
MAKEPOINT(
CASE [count]%4
WHEN 3 THEN [Line_Y_(+)-1]*-10
WHEN 0 THEN [Line_Y_(+)-1]*1
WHEN 1 THEN null
WHEN 2 THEN null
END
,
CASE [count]%4
WHEN 3 THEN [Line_X_(+)-1]*-10
WHEN 0 THEN [Line_X_(+)-1]*1
WHEN 1 THEN [Line_X_(+)-1]*1
WHEN 2 THEN [Line_X_(+)-1]*-10
END
)
END
計算フィールド「POINT_1-2 (line)」の作成
CASE [象限]
WHEN 1 THEN
MAKEPOINT(
CASE [count]%4
WHEN 0 THEN [Line_Y_(+)-2]*-10
WHEN 1 THEN [Line_Y_(+)-2]*1
WHEN 2 THEN null
WHEN 3 THEN null
END
,
CASE [count]%4
WHEN 0 THEN [Line_X_(+)-2]*-10
WHEN 1 THEN [Line_X_(+)-2]*1
WHEN 2 THEN [Line_X_(+)-2]*1
WHEN 3 THEN [Line_X_(+)-2]*-10
END
)
WHEN 2 THEN
MAKEPOINT(
CASE [count]%4
WHEN 1 THEN [Line_Y_(+)-2]*-10
WHEN 2 THEN [Line_Y_(+)-2]*1
WHEN 3 THEN null
WHEN 0 THEN null
END
,
CASE [count]%4
WHEN 1 THEN [Line_X_(+)-2]*-10
WHEN 2 THEN [Line_X_(+)-2]*1
WHEN 3 THEN [Line_X_(+)-2]*1
WHEN 0 THEN [Line_X_(+)-2]*-10
END
)
WHEN 3 THEN
MAKEPOINT(
CASE [count]%4
WHEN 2 THEN [Line_Y_(+)-2]*-10
WHEN 3 THEN [Line_Y_(+)-2]*1
WHEN 0 THEN null
WHEN 1 THEN null
END
,
CASE [count]%4
WHEN 2 THEN [Line_X_(+)-2]*-10
WHEN 3 THEN [Line_X_(+)-2]*1
WHEN 0 THEN [Line_X_(+)-2]*1
WHEN 1 THEN [Line_X_(+)-2]*-10
END
)
WHEN 4 THEN
MAKEPOINT(
CASE [count]%4
WHEN 3 THEN [Line_Y_(+)-2]*-10
WHEN 0 THEN [Line_Y_(+)-2]*1
WHEN 1 THEN null
WHEN 2 THEN null
END
,
CASE [count]%4
WHEN 3 THEN [Line_X_(+)-2]*-10
WHEN 0 THEN [Line_X_(+)-2]*1
WHEN 1 THEN [Line_X_(+)-2]*1
WHEN 2 THEN [Line_X_(+)-2]*-10
END
)
END
計算フィールド「id%25」を作成。1と26、2と27、3と28…というIDの組み合わせを1セットとするために作成。
([Id]-1)%25
「POINT_1-1 (line)」をマークレイヤーに追加。
マークを線に変更し、象限、id%25を詳細に、Idをパスに配置する。
これによりID1~25に設定されている丸から線が伸びる。
計算フィールドid/25-1を作成し、サイズに配置する。
始点が0、終点が‐1になるため、始点が膨らみ終点が細くなるような線を作ることが出来る。
-DIV([Id]-1,25)
同様にPOINT_1-2 (line)をマークレイヤーに追加し同様の設定を行う。
サイズにはid/25-2を作成して配置。
DIV([Id]-1,25)-1
配置した線は「選択項目を無効にする」の設定をしておく。計算フィールド「Color」を作成。選ばれた元素に応じて数字が変わる。
CASE [選択記号]
WHEN "Ca" THEN 1
WHEN "B" THEN 2
WHEN "In" THEN 3
WHEN "Tl" THEN 4
WHEN "K" THEN 5
WHEN "Cu" THEN 6
WHEN "Ga" THEN 7
WHEN "Cs" THEN 8
WHEN "Sr" THEN 9
WHEN "Li" THEN 10
WHEN "Ba" THEN 11
WHEN "Na" THEN 12
WHEN "Rb" THEN 13
ELSE 0
END
Colorの既定のプロパティから色の設定をする。
パレットを追加した「FlameReaction」に設定。
ステップドカラーを14ステップに設定し、詳細から開始を0、終了を13に設定する。
4つのマークレイヤーすべてにColorを配置する。
Lineは不透明度を40%に設定して見た目を調整する。
ツールヒントの調整を行う。
花火のデータと周期表のデータがバラバラなので、パラメーターで受け取れるようにする。
パラメーター「選択色」「選択名(En)」「選択名(Jp)」「選択原子番号」を作成。
「選択原子番号」は整数型、それ以外は文字列型で作成する。
各パラメーターをツールヒントに入れる。
カスタム形状のマークレイヤーのサイズを大きくしておく
マップを「なし」に設定する。
緯度経度の軸の範囲を0~1.2に設定する。
ヘッダーや各種ラインを非表示にする。
アニメーションの設定から、期間を5秒に設定する。
countをいじってみる
第1象限が完成。
第2~4象限も同様に作成する。
第2象限はXをマイナスに、第3象限はX,Y両方をマイナスに、第4象限はYをマイナスにした座標を作成する。基本的にワークシートを複製し、詳細に入ったPOINTやLINEを置き換えれば対応可能
ダッシュボード作成
背景画像を埋め込む。説明文は画像で用意します。
各種ワークシートを配置する。
周期表のアクションを設定する。
パラメーターアクション「色選択」を作成。
ソースシートを周期表に、ターゲットパラメーターを「選択色」、ソースフィールドを「色(Label)に設定する。
パラメーターアクション「元素記号選択」を作成。
ソースシートを周期表に、ターゲットパラメーターを「選択記号」、ソースフィールドを「元素記号(Label)に設定する。
パラメーターアクション「count+1」を作成。
ソースシートを周期表に、ターゲットパラメーターを「count」、ソースフィールドを「count+1」に設定する。これによりクリックするたびにcountが1つ増えていく。
パラメーターアクション「原子番号選択」を作成。
ソースシートを周期表に、ターゲットパラメーターを「選択原子番号」、ソースフィールドを「原子番号」に設定する。
パラメーターアクション「元素名(En)選択」を作成。
ソースシートを周期表に、ターゲットパラメーターを「選択名(En)」、ソースフィールドを「元素(En)(Label)」に設定する。
パラメーターアクション「元素名(Jp)選択」を作成。
ソースシートを周期表に、ターゲットパラメーターを「選択名(Jp)」、ソースフィールドを「元素(Jp)(Label)」に設定する。
周期表を連続でクリックできるような設定を行う。
フィルターアクションで、ソースシートを周期表に、ターゲットシートを周期表のシートに、アクションの実行対象を選択に、選択項目をクリアした結果をすべての値を表示に、フィルターは選択したフィールドでソースフィールドをTRUE,ターゲットフィールドをFALSEに設定する。
完成!
結果
対策むなしく、決勝でChasosoさんに負け、準優勝に終わりました。全然関係ねえ~
しかしまったく理解できてないところから全力でダッシュボードを読み解いて原理を解説するというのはかなり技術的な練習につながったような気がします。
普通にこのアニメーション使って何かしたいっすな・・・
決勝後こんな対策をしてたからアップしてもいいか、という話をChasosoさんにし、公開を快諾してくださりました。本当にありがとうございます。
VizつくりまShow!本戦で1勝出来ただけでもかなりの思い出です。来年は優勝目指していきたいと思います。