テーマの基本 その9
(分岐編)

プログラミングでバッテリーを表現してきましたが、文字を表示したり四角を塗りつぶしたり、比較的単純なことをやってきました。
この先もやることは単純なのですが、考え方や処理が複雑になってくると、その条件によって違うことをしなければならなくなってきます。

ここでは、プログラミングの特長である「分岐」を使って、一味違ったバッテリーを表現してみます。

分岐を学ぶ

条件によって処理を振り分ける方法を知ることから始めましょう。

if 文

分岐する方法は1つではありませんが、代表的なif文だけを紹介します。
逆に、if文1つ覚えておけば何とかなりますので、if文の使い方をきっちり覚えておきましょう。

if文の書き方は、基本的に以下の通りです。
if ( 条件 ) {
 条件が満たされた時の処理
}
この基本形だけでも十分役に立ちます。

例えば、「aが1の時はaに2を入れる」という処理をしようとすると、以下のようになります。
if ( a == 1 ) {
 a = 2;
}

図解するとこんな感じです。

これをフーチャートと呼び、プログラムの流れを理解するのに役立ちます。

こんな感じで進めます。

if 〜 else 文

if だけでも十分なのですが、プログラムを見やすくするために、覚えておいたほうが良いものもあります。
「条件が満たされた時」と、「条件が満たされなかった時」の2つの if 文を並べれば良いのですが、「そうではない時」という書き方を使うと、プログラムが見やすくなります。
それが if 〜 else なのですが、書き方は、基本的に以下の通りです。
if ( 条件 ) {
 条件が満たされた時の処理
}
else {
 条件が満たされなかった時の処理
}

例えば、「aが1の時はaに2を入れ、aが1でない時は3を入れる」という処理をしようとすると、以下のようになります。
if ( a == 1 ) {
 a = 2;
}
else {
 a = 3;
}

図解するとこんな感じです。

if 文を並べると、「そうではない時」という条件も書かなければならないので、この方が見やすい上に、記述量も減ります。

if 〜 else if 文

if だけでも十分なのですが、プログラムを見やすくするために、if 〜 else 文も紹介しました。
Yes か No かだけの処理ならそれでも良いのですが、それで済まないのがプログラミングです。
それは、プログラミングは難しいという訳ではなく、スキルが上がるとやりたい処理が増えてくるからです。

そこで紹介するのが、if 〜 else if 文です。
書き方は、基本的に以下の通りです。
if ( 条件1 ) {
 条件1が満たされた時の処理
}
else if ( 条件2 ) {
 条件1が満たされず、条件2が満たされた時の処理
}
else {
 すべての条件が満たされなかった時の処理
}
if 文を並べても同じように見えますが、条件1を満たさず条件2を満たす場合という条件を記述するよりは、はるかに楽です。

例えば、「aが10以上の時はbに10を入れ、aが5以上の時はbに5を入れ、それ以外の時はbに1を入れる」という処理をしようとすると、以下のようになります。
if ( a >= 10 ) {
 b = 10;
}
else if ( a >= 5 ) {
 b = 5;
}
else {
 b = 1;
}
a の値によって、b が3通りの値を持つことになります。

図解するとこんな感じです。

a が20だった場合、10以上という条件を満たすため、b=10となって一連のif 文による処理が終わります。
もし、if 文を並べた場合、10以上という条件を満たしますが、その次の5以上という条件も満たすため、b の値が書き換えられてしまいます。
つまり、if 文を並べるだけだと、条件を細かく指定しないと、想定外の結果を招きやすくなるのです。

条件を満たさないものを除外していくことで見やすくなり、記述量も減ります。
幾つか条件がある場合は、if 〜 else if を使うと良いでしょう。
フローチャートでも、どんどん分岐していることがお分かりいただけると思います。

バッテリー残量の分岐表示を考える

このタイミングで分岐のページを作った理由が、バッテリー残量表示を残量に応じて変更しようと思ったからです。
20%で赤色になりますが、赤色のフルゲージで20%にすれば、もっと見やすくなると思ったからです。
使い勝手は、使い込まないと分かりませんが、作ってみましょう。

分岐の条件を整理する

バッテリー残量20%を1つの分岐点としますが、これだけだと if 〜 else だけで終わってしまうので、もう1つくらい欲しいところですね。
しかし、実用性を考えると、分岐点は20%の1つでも良さそうなのです。
う〜ん・・・

やっぱり、実用性かなぁ・・・

実用性を取ります!!
という訳で、分岐点は1つにします。
せっかく else if まで紹介しましたが、目的が変わってきますので、実用性重視でいきましょう。

「分岐点は、残量20%の1つとする」
これでいきましょう。

分岐の処理を考える

残量20%を境に表示方法を変えますが、20%までは従来通りとしましょう。
そして、20%以下になったら、20%をこれまでの100%とするゲージに変更することにします。
もちろん、色は赤色です。

こんな感じで分かりますでしょうか?

残量20%でフルゲージを考える

20%で赤く表示されるのは、以前から標準的な動作でしたが、残りが少ないからこそ、はっきり残量を知りたいということで、標準の「バッテリー残量(%)」をオンにして使ってきました。
逆に、数値表示があれば、バッテリー表示はいらないくらいに思っていました。
もし、細かな残量が拡大表示されたら見やすくなるのかなぁ?という、私の以前からのイメージを実現してみたいと思います。

残量20%でフルゲージとは

バッテリー残量20%になったら赤くなりますが、それだけです。
赤いから「少ないんだろうなぁ」と思うものの、どれくらい少ないかがわかりません。
10%も5%も、わずかな差しか無いので、やはり数値表示に頼ってしまいます。
そこで、赤くなる20%を拡大表示して、本来の100%からまた始まる状態になれば、すんごく見やすいのでは無いか!?ということ考えていました。

実際の処理を考える

では、どのようにプログラミングすれば良いのでしょうか?
20%が100%になるのだから・・・

5倍ですね!!



プログラミングする

では、イメージを形にしましょう。
今回の悩み処は、仕様を決める段階でしたので、あとはプログラムに反映させるだけです。

if 文を導入する

もう、分岐の条件も処理もイメージできているので、そのままプログラミングします。

条件分岐を加えたプログラムは、以下の通りです。
(height, percent, charge, low, lpm, m_color, b_color) {

 var canvas = document.createElement("canvas");
 canvas.height = height / 2;
 canvas.width = height;
 var ctx = canvas.getContext("2d");

 ctx.strokeStyle="rgb(" + b_color.slice(0, 3).join()+ ")";
 ctx.lineWidth = 3;
 ctx.strokeRect(0, 0, height, height/2);

 var s = 3;
 var rectWidth;
 if ( percent > 20 ) {
  rectWidth = Math.round((height-s*2)*percent / 100);
 }
 else {
  rectWidth = Math.round((height-s*2)*percent*5 / 100);
 }
 ctx.fillStyle="rgb(" + m_color.join()+ ")";
 ctx.fillRect(s, s, rectWidth, height/2-s*2);

 return canvas.toDataURL("image/png");
}
今回の rectWidth は、条件によってその中身が変化するので、変数宣言だけ先にやっておきました。
ぶっちゃけ、宣言しなくても動きます。

条件分岐は、20%を超えていればそのまま表示し、20%以下だとその表示を5倍にするというものです。

結果は、こんな感じです。

ここまで通常表示だったものが・・・

20%でフルゲージになり・・・

フルゲージの割合を保ったまま減っていきます。

長年の念願が叶いました!!


このサンプルのダウンロード ー> basic9_1.zip

仕上げる

if 文を導入して、それらしいプログラムになりました。
動作もイメージ通りで、問題ありません。
ただ、プログラムというのは動けば良いというわけではありません。
スポーツで、勝てば何やっても良いわけでは無いのと同じです。
しかも、プログラムというのは、後から見ると理解不能なものです。
自分で作ったプログラムでさえ、「誰がこんなの作ったんだ?」と思うほど理解しにくいこともあるので、作り込みの段階で、ある程度「美しさ」を追求しなければなりません。
この「美しさ」というのは、簡素で無駄がなく、誰が見ても理解しやすいことです。

イメージ通りの動きを得られましたので、プログラムを美しくしていくことを考えます。

似たような記述をまとまる

手始めに、似た記述があればまとまるのですが、どこに似た記述があるのでしょうか。
一目で分かるのは、rectWidth ですね。

では、どのようにまとめましょうか。
分岐の処理の違いは、5倍にするかどうかなので、「5倍にする」にスポットを当てましょう。
5倍にしなければそのままで良いのですから、if 文も簡単になります。
問題は、Math.round のタイミングです。
数値計算をした後に丸めなければならないので、後でまとめて丸めることにします。

似たような記述をまとめたプログラムは、以下の通りです。
(height, percent, charge, low, lpm, m_color, b_color) {

 var canvas = document.createElement("canvas");
 canvas.height = height / 2;
 canvas.width = height;
 var ctx = canvas.getContext("2d");

 ctx.strokeStyle="rgb(" + b_color.slice(0, 3).join()+ ")";
 ctx.lineWidth = 3;
 ctx.strokeRect(0, 0, height, height/2);

 var s = 3;
 var rectWidth = (height-s*2)*percent / 100;
 if ( percent <= 20 ) {
  rectWidth = rectWidth * 5;
 }
 rectWidth = Math.round( rectWidth );
 ctx.fillStyle="rgb(" + m_color.join()+ ")";
 ctx.fillRect(s, s, rectWidth, height/2-s*2);

 return canvas.toDataURL("image/png");
}
通常表示の rectWidth を求めて、20%以下であればそれを5倍します。
5倍にされてもされなくても数値を丸めることにより、同じ結果を得ることができます。


このサンプルのダウンロード ー> basic9_2.zip

バグを取る

ここにもバグがありました。
プログラムミスではありません。

それは、20%でフルゲージになることを確認し、充電を始めた時に気付きました。
20%でフルゲージは、今回の目的ですので問題ありません。
充電時に緑色になることも、仕様ですので問題ありません。
20%で充電を始めると、以下のようになりました。
当たり前ですよね。
しかし、この状態だと、20%なのに満充電のように見えてしまいます。
それは不都合でしかありませんので、充電時は通常表示にする必要があります。

そこで、「20%以下で充電していない時」という条件にすることにします。

バグ取り後のプログラムは、以下の通りです。
(height, percent, charge, low, lpm, m_color, b_color) {

 var canvas = document.createElement("canvas");
 canvas.height = height / 2;
 canvas.width = height;
 var ctx = canvas.getContext("2d");

 ctx.strokeStyle="rgb(" + b_color.slice(0, 3).join()+ ")";
 ctx.lineWidth = 3;
 ctx.strokeRect(0, 0, height, height/2);

 var s = 3;
 var rectWidth = (height-s*2)*percent / 100;
 if ( percent <= 20 && charge == false) {
  rectWidth = rectWidth * 5;
 }
 rectWidth = Math.round( rectWidth );
 ctx.fillStyle="rgb(" + m_color.join()+ ")";
 ctx.fillRect(s, s, rectWidth, height/2-s*2);

 return canvas.toDataURL("image/png");
}
「charge」は、充電しているかどうかの情報が格納されているので、「true」であれば充電中ですし、「false」であれば充電していないことになります。
「充電していない時」という条件は、「charge == false」となり、20%以下の条件に対し、「&&」でつなげました。
これにより、「20%以下」という条件と「充電していない」という条件の両方が満たされた時、rectWidth を5倍にするという処理が実行されることになります。

結果は、こんな感じです。

ここまで通常表示だったものが・・・

20%でフルゲージになり・・・

充電すると、通常表示に戻ります。

これで、思った通りの動作になりました。


このサンプルのダウンロード ー> basic9_3.zip

仕上げる パート2

なぜかパート2です。
これは、JavaScript的なものではなく、Lithium Ion的なものです。
JavaScriptとしては完成していますが、Lithium Ion的には、まだ終わっていません。

Lithium Ionのテーマでは JavaScript を使いますが、Lithium Ionのテーマに限り、JavaScriptの記述を省略できる項目があるのです。
テーマの基本2の最初に、「function renderBattery()」という関数で始めましたが、これらほとんどを省略して () から始めました。
これも、Lithium Ion的な省略です。

ここで省略するのが、「if」です。
例えば、以下の if 文があるとすると・・・
if ( a == b ) {
 c = d;
}
「aとbが同じなら、cにdを入れる」という条件処理です。
これが、以下のように書き換えることができます。
a==b&&(c=d); 簡単なのか、難しいのか、よくわかりませんが、Lithium Ion側がこのような書き方を提供してくれているので、慣れておいた方が良いのでしょうね。

これを使って書き換えたプログラムは、以下の通りです。
(height, percent, charge, low, lpm, m_color, b_color) {

 var canvas = document.createElement("canvas");
 canvas.height = height / 2;
 canvas.width = height;
 var ctx = canvas.getContext("2d");

 ctx.strokeStyle="rgb(" + b_color.slice(0, 3).join()+ ")";
 ctx.lineWidth = 3;
 ctx.strokeRect(0, 0, height, height/2);

 var s = 3;
 var rectWidth = (height-s*2)*percent / 100;
 (percent<=20 && charge==false) && (rectWidth *= 5);
 rectWidth = Math.round( rectWidth );
 ctx.fillStyle="rgb(" + m_color.join()+ ")";
 ctx.fillRect(s, s, rectWidth, height/2-s*2);

 return canvas.toDataURL("image/png");
}
rectWidth = rectWidth*5 という記述も、何気に書き換えてしまいました。
このような書き方があることも、覚えておくと良いでしょう。


このサンプルのダウンロード ー> basic9_4.zip

仕上げる パート3

え〜!!って感じのパート3です。
これ以上仕上げることがあるのでしょうか。
実は、仕上げの流れに乗ってしまいましたが、オマケ的なものです。

パート2では、Lithium Ion側の計らいで if を省略する方法を紹介しましたが、JavaScriptでも if を省略することができます。
「条件演算子」というものを使いますが、その文法は以下の通りです。
条件式 ? 条件を満たした時の式 : 条件を満たさない時の式
例えば、a == b ? 1 : c = d とあった場合、aとbが同じなら1が返り、aとbが違うならcにdが入れられます。
戻り値は、数字でも式でも処理でもOKです。

この条件演算子を使って書き換えたプログラムは、以下の通りです。
(height, percent, charge, low, lpm, m_color, b_color) {

 var canvas = document.createElement("canvas");
 canvas.height = height / 2;
 canvas.width = height;
 var ctx = canvas.getContext("2d");

 ctx.strokeStyle="rgb(" + b_color.slice(0, 3).join()+ ")";
 ctx.lineWidth = 3;
 ctx.strokeRect(0, 0, height, height/2);

 var s = 3;
 var rectWidth = (height-s*2)*percent / 100;
 rectWidth *= (percent<=20 && charge==false) ? 5 : 1;
 rectWidth = Math.round( rectWidth );
 ctx.fillStyle="rgb(" + m_color.join()+ ")";
 ctx.fillRect(s, s, rectWidth, height/2-s*2);

 return canvas.toDataURL("image/png");
}
パート2で、rectWidth = rectWidth*5 を、rectWidth *= 5と 書き換えたのですが、今回も同じ書き方をしています。
条件を満たせば5倍し、満たさなければそのままの1倍ということになります。

結論としましては・・・
if 文は必要ないぢゃん!!
となってしまいます・・・

慣れもありますので、if 文が良い方は if 文で良いと思います。
if 文を使わないことにカッコ良さを感じるなら、それで良いと思います。
ちなみに、私は if 文を使います。


このサンプルのダウンロード ー> basic9_5.zip



当サイトの更新状況を、アラートで表示するかどうかの設定をします。


保存する

その機能で月額1500円もするのですか??
その機能なら年額1500円で手に入りますよ!

当サイトもこちらのレンタルサーバーを利用しています。

Copyright (C) 2007 Bokechans.net All Rights Reserved.