- トップ
- iOS10
- Lithium Ion のテーマを作る
- テーマの基本 その9(分岐編)
テーマの基本 その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
当サイトの更新状況を、アラートで表示するかどうかの設定をします。
保存する