ホーム > デベロッパ > J2ME / MIDP プログラミング > 第 5 回

第 5 回 : インターフェイス構築のヒント

はじめに

画面デザインとそのコーディングに関するノウハウをまとめます。

グラフィック関連 API、色、コントラストの付いたインターフェースと平面的なインターフェースの比較、コントラストのつけ方、 IM "improve" での実際のコーディングについての話です。


画面デザインとプログラム

携帯アプリなどを作っていると、機種によって画面サイズが違うことが問題になることが有ります。その為、各機種ごとにデザインを作り直したり、画像を作り直したりしなければなりません。画面デザインを PhotoShop などのレタッチソフトやその他のグラフィックソフトを使用してデザイナーがデザインすると、確かに見栄えの良いデザインにはなるのですが、複雑な陰影を付けられたりするともはやコーディングで表すことは出来ません。

この場合、画面デザインその物をイメージとして幾つかに切り分けて、プログラマーはそれを貼り付けるだけという状況になるかと思います。そうすると、動的にデザインを変更出来ないため、各機種ごとにデザインを変更したりプログラムを修正する必要が発生してしまいます。画面デザインの段階でプログラマーがコーディングしやすい設計にしておくと、動的に画面を変更したりカラーテーマを動的に入れ替えたりと、少し見栄えは落ちますが、得られる利益は大きいと思います。また、カラーテーマを入れ替えたりする様な事をイメージで行おうとした場合、数通りのイメージのセットを全部保持しておくかネットワークからダウンロードしてこないといけないなど、容量面でも速度面でもコーディングによる入れ替えにはかなわないと思います。

当コラムはプログラマーを対象にしていますので、画面デザインをコーディングによって表現すると言うことに重点を置いています。コーディングで表現できるデザインはアプリの容量や実行速度、またグラフィック関連 API の充実度による制限などもあり、必ずしもイメージで表現する方法に優る物では有りませんが、プログラマーの立場に立ち少しでもコーディングしやすく少しでも見栄えの良いソフトを作る参考になればと思います。ちなみに、イメージを全く使用しないでコーディングのみで表現しようというわけでは有りません。イメージに頼った方が効率的な場合も多々あります。イメージとコーディングの使い分けの基準は有る程度のノウハウが必要かも知れませんが、慣れてしまえば感覚的にデザインできるようになるかと思います。

図形と色の基本事項

今更・・・という話かも知れませんが、画面デザインをコーディングで表す場合に重要な点は、図形と色です。この分野はゲームプログラマーなどは得意としているかも知れませんが、画面構築作業をしないプログラマーにとっては悩みの種かも知れません。そこで、今回はちょっとしたコツさえつかんで置けばそれなりにそれなりのインターフェースが作れるということを紹介します。

図形

まず図形に関してですが、一般的なインターフェースで現れる図形は線分・四角形・円だと思います。特に線分と四角形はお互いに関係が深いのでそれを取り上げます。

MIDP をはじめ様々な環境のビットマップ描画システムでは、ピクセルは画面左上から(0,0)と始まり(1,0)(2,0)と数えていきます。線分を引くメソッドは殆どの場合あるピクセルからあるピクセルへ線を引くという概念で記述されているため、drawLine(0,0,2,0); とすると3ピクセル分の線を引いたことになります。しかし、四角形を描くメソッドは必ずといっていいほどピクセルとピクセルの間の線を数えており、drawRect(0,0,2,0); とすると何も描かれません。もし drawRect を使用して上の drawLine を同じ結果を得たい場合、drawRect(0,0,3,1); としないといけないのです。複雑な画面デザインをイメージではなくコーディングで表したい場合、特に上記の線分と四角形の長さの数え方の違いに注意しておかないと無駄に時間を費やす事になります。

図1 座標の数え方の違い
座標の数え方に関して

次に色に関してですが、大抵の環境では赤・緑・青の3原色をそれぞれ8ビットで表します。インターフェースをちょっと格好よく見せたりするのにもっとも簡単で効果の大きい方法は、光の当たっている部分と影になっている部分を描くことです。 こうすることで、ベタ塗りのような面白みの無いインターフェースから開放されるでしょう。明るい部分と暗い部分を作り出すための一番簡単な方法は、ベースとなる色から それぞれ同じ程度に明るくしたり、暗くしたり演算することです。明暗をつけるときの演算は、赤・緑・青それぞれに同じ量だけ演算をします。ここで問題となるのは、8ビットで表現できる範囲を越えてしまう要素が存在した場合に色相や彩度がずれてしまうことです。 人間にとって色相や彩度のずれない範囲と言うのは意外に狭く、色相によっては更に使いにくい色も有ります。厳密に人間の目に合うように明度を変更する場合、色空間を HSV 空間に変更するなどしてから演算してもう一度 RGB 空間に戻せばいいのですが、リアルタイムで演算して描画するには少し重い処理です。厳密な処理よりは速度を取るということで RGB 空間のままで大まかな演算を行うという方が実用的でしょう。

下の図は基準色から赤・緑・青それぞれに同じだけ演算したときの結果を示した物です。それぞれに同じだけ演算すれば当然の結果として、8ビットの範囲を超える要素が出てきてそれが色のズレになってきます。赤枠で囲った範囲は8ビットの範囲を超えない部分です。8ビットの範囲を超えた場合、彩度の違う色との区別が出来なくなってしまう 事がわかるかと思います。(下の段に行くほど彩度がきつくなり、また基準色その物が明るくなります。それぞれの段の真ん中の基準色から左右に演算しています。)

図2 簡易演算の範囲
簡易演算の範囲

インターフェースを比較する

では、基本事項を理解したところでベタ塗り調のインターフェースとコントラストの あるインターフェースを比較してみましょう。

図3 友達リスト(コントラスト無し) 図4 友達リスト(コントラスト有り)
友達リスト(コンストラスト無し) 友達リスト(コンストラスト有り)
図5 メニュー表示中(コントラスト無し) 図6 メニュー表示中(コントラスト有り)
メニュー表示中(コントラスト無し) メニュー表示中(コントラスト有り)

上の比較画像は、左側の画像は右側の画像から明るい部分と暗い部分を取り去っただけの 違いしか有りません。つまり右側のデザインは fillRect や drawRect を本文後半で出てくる draw3DRect で 置き換えたりイメージにコントラストを付けただけです。これだけの変更で見た目は大きく変わってきます。 あなたはどちらのアプリを使いたいと思うでしょうか?(友達リストに関しては平面的なデザインも 結構綺麗なような気もしますが・・・)

四角形や円でのコントラストの付け方

それでは、実際にデザインをソフトウェア的に表現する時にどうなるのか 幾つかのパターンを見てみます。ここでは上のインターフェースの比較で用いた コントラストのある四角形や円を用いたデザインを対象にします。

四角形

図7 コントラストの付け方(四角形)
コントラストの付け方

明暗の有る四角形を描くのは比較的簡単です。上の図を見てもらえればわかると思いますが、左上の線・右下の線・中央の四角形・右上のピクセル・左下のピクセルという構成要素から出来ています。場合によっては右上と左下のピクセルは外側の 基準色を使用することも有ります。この場合、上の図より四角形の角がもう少し丸みを 帯びて見えることでしょう。上の図の様な画像を描くには1回の drawRect 呼び出しと 4回の drawLine 呼び出しで描くことが可能です。4回の drawRect 呼び出しでも実現できますが、実行速度の速い方を取ればいいと思います。

図8 コントラストの付け方(円)
コントラストの付け方2

次に、明暗のある円を描くのは容易なことでは有りません。円弧を描くメソッドが 有る環境ならまだ実現しやすいですが、そうでない場合、円の外側に明暗を付けるのは 厄介な作業です。よって、円の場合は動的に変更される描画処理ではなくて、その部分の画像だけをイメージとして描画したりする方が効率的なことが多いです。以上のことから動的に変更したい部分はなるべく四角形を用いたデザインにする。 円を含む物や丸みのある物はイメージとして完成された形で保持しておく。このような 方法を取るほうが効率がよいということになります。三角形などもイメージとして保持しておく方が良いでしょう。

ちなみに、図7・図8 を実際にビットマップで表すと以下の図のようになります。 (ただし、実際の大きさにしてしまうと小さすぎて見分けが付かないので、2倍に拡大 してあります。)

図9 実際の見え方
実際の見え方

工夫

ところで、ここまで見てきておや?変だなぁ・・・と思われた事は無いでしょうか? 図7・図8のそれぞれの左右の画像を比べると左側が出っ張っていて、右側が凹んでいるように見えるかと思いますが、明るい部分と暗い部分の色の付け方が逆さまなだけです。つまり、コントラストの付け方ではなくて光源が逆転した場合と区別が付かないのです。これでは、本当はどちらが出っ張っているのかわかりません。しかし、周囲のデザインによる影響やほとんどの人の思いこみと錯覚によって左側が出っ張って見えるかと思います。厳密に表現したい場合は、陰の部分の色を濃くしたり線分を太くしたりデザインをさらに工夫するなどの方法が有ります。

実際のコーディング

では、実際にコーディングする時にはどのようなコードになるのかを見て行きたいと思います。様々な環境のグラフィック関連のメソッドにdrawRect や fillRect などの 四角形を描くメソッドがあると思いますが、これに陰影を付けて立体的に見えるようにしたメソッドの例を示します。draw3DRect は指定された座標の中を基準色で 塗りつぶし、1ピクセル外側に光の当たっている部分と影の部分を表す線分を描画します。drawRect や fillRect の替わりに draw3DRect を使用するだけでコントラストの効いたデザインに変わるでしょう。

// Canvas クラスの paint メソッドなど

void paint(Graphics g// グラフィックスオブジェクト

 ) {

intw= getWidth();

inth= getHeight();



// 画面の大きさでコントラストの付いた四角形を描きます

draw3DRect(g,1,1,w - 1,h - 1,0x00808080,0x00A0A0A0,0x606060);

return;

}// paint //



// コントラストの付いた四角形を描きます

void draw3DRect(Graphics g// グラフィックスオブジェクト

 ,int x// X座標

 ,int y// Y座標

 ,int dx// 幅

 ,int dy// 高さ

 ,int b// ベースの色

 ,int l// 明るい部分の色

 ,int s// 暗い部分の色

 ) {

// ベースの部分を描きます

g.setColor(b);

g.fillRect(x,y,dx,dy);

// 左辺と上辺の明るい部分を描きます

g.setColor(l);

g.drawLine(x,y,x + dx - 2,y);

g.drawLine(x,y,x,y + dy - 2);

// 右辺と下辺の暗い部分を描きます

g.setColor(s);

g.drawLine(x + dx - 1,y + 1,x + dx - 1,y + dy - 1);

g.drawLine(x + 1,y + dy - 1,x + dx - 1,y + dy - 1);

return;

}// draw3DRect //

上記のメソッドは指定された四角形の外側に1ピクセルの枠のような感じで 明るい部分と暗い部分を描きます。ちなみにお気づきかと思いますが、明るい部分の色と暗い部分の色の引数を入れ替えれば凹んだ四角形を描くことが出来ます。当メソッドは 図4の友達リストの土台を書くのにも使用されており、様々な応用が利くと思います。

improve での実際

次に、当連載で作成中の improve の場合のデザインの話をしたいと思います。improve のデザインは比較的シンプルな物を目指しています。(実は今までのデザイン の使い回しという話も・・・)大まかに分けると、ティッカー部分・友達リスト部分・メッセージング部分・メニュー部分となります。それぞれの部分は明暗を持った 四角形で表現されています。ティッカー部分は上辺と下辺だけにコントラストが付けてあり、左辺と右辺には付いていません。その理由ですが、左辺と右辺に コントラストを付けると文字が流れていくときに、あまり見栄えが良くないという私の非常に主観的な判断に依る物ですが、コーディングにさほど影響する物ではないので些細なことです。ちなみに、drawRect 1回と drawLine 2回で表現出来ます。 友達リスト部分ですがリストの土台を表現するには drawRect 1回と drawLine 4回が必要です。バディーの名前は drawString、状態を示す丸いアイコンは イメージで表現しています。また、メッセージ中であることを示す右向きの三角形とリストスクロールの上向きと下向きの三角形もイメージで表現しています。友達リスト画面の構成を下の図に示します。各レイヤーごとにコーディングでの表現とイメージでの表現が 綺麗に切り分け出来ています。実際の描画時は下のレイヤーから描画していきます。描画がすべて終わると図4の様な見た目になります。

図10 友達リスト画面の構成要素
友達リスト画面の構成要素

番号 レイヤー名 役割
土台レイヤー 友達リストの背景を描きます
選択フィールドレイヤー 選択されているバディーを表すためのカーソルを描きます
名前レイヤー バディーの名前を描きます
アイコン枠レイヤー アイコンが填る枠を描きます
状態アイコンレイヤー バディーの状態を表すアイコンを描きます
矢印レイヤー リストのスクロール状態などの矢印を描きます

メッセージング部分の土台は友達リスト部分の土台と全く同じです。左向きの 三角形と状態アイコンも同様にイメージを用いています。  ここでポイントになるのは、状態アイコンのイメージと三角形のイメージをどうデザインするかです。improve のデザインは画面サイズ非依存、カラーテーマをごっそり差し替え可能なデザインを目指しています。ティッカー、友達リストの 土台とメッセージングの土台は動的に描画しているので、カラーテーマの変更にも何の 影響も受けないことはわかるかと思います。後は、動的に描画出来ないアイコン部分と 三角形部分をどうするかです。アイコン部分を拡大すると、アイコンが填り込む穴を 表現するための円形の枠とアイコン本体に分離出来ることがわかると思います。

図11 アイコン部分の拡大図
アイコン部分拡大図

アイコン本体は色が変わりますが、枠の色は非選択状態と選択状態の2色です。 なぜなら枠の色は土台部分に対する明暗であるためです。カラーテーマを変更すると 土台部分の色も変更されることが予想されます。枠の色は土台部分の色に対する明暗 なのでこの部分が影響を受けることになります。以上の点を踏まえてアイコン部分を どう作成するのがもっとも効率的かですが、カラーテーマ分×選択非選択の2通りだけ 枠の画像を用意する必要が有るのは仕方がないと思われます。逆に考えれば、用意 できる枠の数分のカラーテーマしか設定出来ないことになります。アイコン本体は カラーテーマには影響されず何時も一定の色だというデザインにして、透過イメージを 使用できると仮定すれば、イメージの数はカラーテーマ分の枠のイメージ数×2と アイコン本体の色数分という事になります。透過イメージが使用できない場合はカラーテーマ分の枠のイメージ数×2×アイコン本体の色数分のイメージを用意する必要が でてきて現実的で無いかも知れません。もし、アプリのサイズを気にしないときや透過 イメージを使用しない方が描画速度が格段に高速であるなどの場合は後者の方法は 有用であると思われます。

三角形の矢印部分は、カラーテーマに影響されにくい色にして平面的なデザインに することで、用意するイメージの数を減らすという方法をとっています。周囲の オブジェクトとの関連などで一番見栄えのよく簡単に表現できる物を取った結果平面の 三角形になりました。

ところで、現状の improve ではカラーテーマを切り替えるコードが入っていない ためアイコン部分も簡略化されており、枠とアイコン本体が一つのイメージで表現 されています。よって、イメージの数はアイコン本体の色数分×選択非選択の2通りと なっています。また、三角形の矢印も黒など汎用的な色ではなく土台の色に依存した 色を使用しています。上記で示したように、アイコン部分の構成を変更し三角形の色を 汎用的な色になるように improve のコードを書き換えれば、すぐにでもカラーテーマ 切り替え可能な IM になるでしょう。

最後に

当コラムは、プログラマー向けということもあり、デザインに関してコーディングで 実現可能な物を良しとするような方向性で書いてきました。その点で見れば、 デザイナーやアプリの企画をする人やユーザからしてみれば少し物足りないデザインに なってしまうかも知れません。ゲームやデザイン重視のアプリよりは IM や電話帳や ビジネスアプリなど少し堅い表現が似合う分野のアプリを作るときの参考になればと 思います。

ソフトウェアのインターフェースのデザインと言う物は、コーディングでの表現とイメージでの表現の混在した、それぞれのメリットを併せ持った物が良いと私は 考えています。イメージだけでは動的な変更は不可能であるし、コーディングだけでは シンプルすぎて面白味のないインターフェースになってしまうと思います。どこまでを コーディングで表現し、どこからをイメージで表現するかということの基準は、経験で 判断する部分が多いと思いますが、プログラマー、デザイナーともにお互いの可能な 事項と不可能な事項を理解してインターフェースを設計すればさらに使いやすくて 見栄えの良いアプリケーションが世に出てくると考えています。