Date:  Wed, 23 Apr 2008 18:13:24 +0900
Subject:  【オブジェクト倶楽部: 2008-16号】
X-Mail-Count: 00238

       ┏━━━━━━━━━━━━━━━━━━━━━━━━━━■
       ┃                         ■┃
      ●┃● ● オ ブ ジ ェ ク ト 倶 楽 部   ■ ┃
       ┃                       ■  ┃
       ┗━━━━━━━━━━━━━━━━━━━━━━■━━━┛
                          No.232 2008/04/23

■ I N D E X
┃
┣【Topics】「受託開発とエンジニアの幸せ」トークイベント&懇親会のお知らせ
┣【コラム】僕の営業日記 [2]
┗【プログラミング】Flex2で体験するリッチクライアント[5]


〇━━━━━━━━━━━━━━━━━━━━━━━━━━━T o p i c s━
 〇 「受託開発とエンジニアの幸せ」トークイベント&懇親会のお知らせ
  〇 〇━━━━━━━━━━━━━ ━━・ 
オブジェクト倶楽部より岡島幸男が『受託開発の極意』(技術評論社)を刊行い
たしました。多くの皆さんに読んでいただいてとてもうれしいです。
そこで、刊行を記念いたしましてイベント開催のご案内です。連休中の開催と
なってしまいましたが、皆さんにお目にかかれますことを楽しみにしています。
ぜひお越しください!!

≪トークイベント≫
タイトル : 「受託開発とエンジニアの幸せ」刊行記念トークセッション
日  時 : 5月1日(木) 19:00〜
会  場 : ジュンク堂書店 池袋本店 4F喫茶スペースにて
お申込み : ジュンク堂書店池袋本店にて
       1階 案内カウンターにて。電話予約可。
定  員 : 40名
講演予定 : 岡島幸男、天野勝、角谷信太郎
詳  細 : ジュンク堂書店
      http://www.junkudo.co.jp/newevent/talk-ikebukuro.html

≪懇親会≫
日  時 : 5月1日(木) 21:00〜
場  所 : 個室・炉端料理 かこいや 池袋東口店
       http://r.gnavi.co.jp/kakoiya8/
参 加 費 : 4,000円
お申込み : 下記ページからお願いします
http://chosuke.rumix.jp/main.aspx?id=1LKSJ6cGsmIzCEGJUs5IhjPCjy2xmCZU

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ■━
■
┗【コラム】僕の営業日記 [2] 
            顧客から感謝される、ということ

こんにちは。Hiroshiです。今回も、僕が営業をしている中でいろいろ体感した
ことを皆様と共有できればと思っています。

ここのところ年度末を迎えたということもあり、幾つかのプロジェクトが終了
しました。足掛け1年もやっていたものもあれば、数ヶ月間のものもあり、気が
つけばこんなに時間は過ぎていたのか、という感じです。御礼も兼ねて訪問さ
せて頂くと、「去年の今頃始めての打合せをしましたよね」と、昔話に花が咲
くものです。
どこへ行ってもいただくことができたのが「ありがとうございます」、という
感謝の言葉でした。当たり前のことかも知れませんが、やはり顧客から感謝の
言葉を頂けるのは、非常にうれしいことです。これまでのプロジェクトの始ま
りから終わりまでかかわってきた立場から、何が良かったのか、をご紹介でき
ればと思います。

効果が出たということは前提にあるとして、以下の2点が良かったのではと考え
ました。

●顧客要望の背後にある想いを合意し、柔軟に対応できたこと
ファシリテーション等のコミュニケーションスキルや、オブジェクト指向やモ
デリング等の技術スキルを向上させたい、というご要望を頂くことは多々あり
ます。しかし、単にそのスキルを向上させることが目的ではなく、その背後に
は何かしらの想いがあります。コミュニケーションスキルを向上させたいとい
う背後には、現場のやらされ感や閉塞感を打破したいという想いがあったり、
技術スキルを向上させたいという背後には、新しい技術にふれることで刺激を
受けて現場の活性化に繋げたいという想いがあったりしました。
その想いを汲み取ることが、現実的に使える解決策となります。そのような策
が提示できたことと、それにあわせて、既存にあるやり方だけでなくカスタマ
イズできたのが良かったのでは、と思っています。

●目的を見失いかけた時には、目的は何だったっけ?と立ち止まれたこと
提案通りに事が進み、うまく解決!ということはなかなかありません。ありが
たいお言葉を頂いた顧客とも、全てが順調に進んだことはありませんでした。
どこかで、認識違いや、話がずれていったこと、大なり小なりありました。そ
の時に、おかしいものはおかしいとお互いが立ち止まって目的を確認しあうこ
とができました。気持ちを隠しながら進めることはできたかも知れませんが、
お互いモヤモヤしたものを抱えていたかも知れません。逆に一緒に見つめ直す
ことで、信頼関係も構築できたと思っています。よく、怒られる時が信頼関係
を築くチャンスだ、と聞きますが、正にそれの連続だったということです。
連続過ぎるのは考え物ですが・・・

最後に、顧客満足度の向上、というと何か薄く感じますが、一度感謝される味
を覚えると、自信にもなり、感謝され中毒となってきます。また、来年、うれ
しいお言葉をいただけるよう頑張ろう!と思います。
皆さんも、いい意味での中毒者を目指してみては如何でしょうか。(Hiroshi)
_______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=H006-1&choice=0
普通:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=H006-1&choice=1
イマイチ:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=H006-1&choice=2

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ■━
■
┗【プログラミング】Flex2で体験するリッチクライアント[5]

先日、Opera[*1]のイベント、Opera Backstage Tokyo[*2]に参加してきました。
普段何気なく使っていると思いますが、様々なTipsや今後の展望などが聞けて、
楽しいイベントでした。当日はLTも行われ、私も先頭バッターとして大役?を
果たして来ました。えーっと、今月はMac話題はなしです・・・

さて前回[*3]はカスタムコントロールを使って、画像を表示するサンプルを紹
介しました。今回はその画像を加工して表示します。画像の加工はいろいろあ
りますが、Macユーザとしては外せない鏡面効果を付けてみましょう。
今回のメルマガでは、カスタムコントロール(ImageReflector.as)を修正してい
きます。

■ファイルの準備
前回のファイルに修正を加えていきますので、まだの方はバックナンバーを確
認してください。

■インポート宣言の追加
以下のインポート宣言を追加します。
       import mx.events.FlexEvent;
       import flash.net.URLRequest;
       import flash.display.Loader;
       import flash.display.Shape;
       import flash.display.Bitmap;
       import flash.display.BitmapData;
       import flash.display.DisplayObject;
       import flash.display.GradientType;
       import flash.events.Event;
       import flash.geom.Matrix;
       import flash.geom.Point;
       import flash.geom.Rectangle;

■メンバ変数の追加
ImageReflectorクラスにメンバ変数を追加します。

       public class ImageReflector extends UIComponent
       {

           private var _invalidatedReflection:Boolean = false; // 鏡面加工したかどうかのフラグ
           private var _imageLoader:Loader = null; // オリジナル画像ローダー
           private var _imageShape:Shape = null;   // 画像の描画領域
           private var _imageShapeBitmap:BitmapData = null; // オリジナル画像データ
           private var _reflectionShapeBitmap:BitmapData = null; // 鏡面画像データ

■commitProperties()の修正
以下のようなコードに修正となります。

           override protected function commitProperties():void
           {
               if (_imageLoader == null) {
                   initLoader();
               }
               invalidateDisplayList();
           }

具体的な変更イメージが掴めないと思うので、initLoader関数の処理も見てみ
ましょう。

           private function initLoader():void
           {
               _imageLoader = new Loader(); // Loaderを生成。
               _imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, function():void {
                   // (a) UIComponentの部品を作成
                   _content = UIComponent(new Image());
                   Image(_content).width = _imageLoader.width;
                   Image(_content).height = _imageLoader.height;
                   addChild(_content);
                   // (b) 実際のコンテンツの描画領域を作成する。
                   _imageShape = new Shape();
                   _content.addChild(_imageShape);
                   // (c) _imageLoaderを描画用のBitmapDataに変換しておく
                   _imageShapeBitmap = new BitmapData(_imageLoader.width, _imageLoader.height, true 0x000000);
                   _imageShapeBitmap.draw(_imageLoader);
                   // (d) 鏡面画像を作成して、BitmapDataに変換しておく
                   var reflectionBitmap:Bitmap = createReflectionBitmap(_imageShapeBitmap);
                   _reflectionShapeBitmap = new BitmapData(reflectionBitmap.width, reflectionBitmapheight, true, 0x000000);
                   _reflectionShapeBitmap.draw(reflectionBitmap);
                   // (e) 背景描画が完了したら、鏡面効果を作成する。
                   _content.addEventListener(FlexEvent.UPDATE_COMPLETE, invalidateReflection);
               });

               // (f) 画像を読み込む
               _imageLoader.load(new URLRequest("http://ec1.images-amazon.com/images/P/4839923221.0._SL200_SCLZZZZZZZ_.jpg"));
           }

前回のサンプルでは、(a)の部分で、Image.dataに値をセットすることで画像を
出していましたが、今回はかなり異なります。これはオリジナルの画像を鏡面
加工するには、元の画像の読み込みが完了していなければならないためです。
Imageを使って画像を表示する方法は便利なのですが、読み込み状況まで制御す
ることができません。このような場合は、Loaderクラスを使って画像を読み込
むことができます。
(f)で画像の読み込みを命令すると、完了イベント(Event.COMPLETE)を受け取れ
ます。イベントを受け取ると、(a)から処理を実行します。
(b)で描画領域を作成します。描画領域はShapeと呼ばれる単純な描画コンポー
ネントを使います。Flex本ではSpriteを使うケースも多いのですが、使い分け
としては、さらに子供の要素を追加する場合はSprite。単純な描画枠ならShape
という理解でよいでしょう。Shapeの方がSpriteよりも使用メモリが少ないとい
う利点もあります。
(c)で取得した画像をビットマップデータに変換しておきます。
_imageShapeBitmap.draw(_imageLoader) のように書くと、ロードした画像を簡
単にビットマップとして扱えるようになります。
(d)で鏡面画像を作成して、_contentの子オブジェクトの更新イベントで
invalidateReflection()が呼ばれるようにしておきます。

■鏡面画像を作成する
鏡面画像を作るには、以下のコードの(a)〜(c)の手順を実施するのが一般的です。

           private function createReflectionBitmap(target:BitmapData ):Bitmap
           {
               var kFalloff:Number = .9; // 鏡面効果のグラデーション長
               var reflectionBitmap:Bitmap = null;
               var tw:Number = Math.max(1,target.width);
               var th:Number = Math.max(1,target.height);
               var rect: Rectangle = new Rectangle(0, 0, target.width, target.height);
               // (a) グラデーションパターンを作成。
               var alphaGradientBitmap:BitmapData = new BitmapData(tw, th, true, 0x00000000);
               var gradientMatrix: Matrix = new Matrix();
               var gradientShape: Shape = new Shape();
               gradientMatrix.createGradientBox(tw, th * kFalloff, Math.PI/2,
                   0, th * (1.0 - kFalloff));
               gradientShape.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF],
                   [0, 1], [0, 255], gradientMatrix);
               gradientShape.graphics.drawRect(0, th * (1.0 - kFalloff),
                   tw, th * kFalloff);
               gradientShape.graphics.endFill();
               alphaGradientBitmap.draw(gradientShape, new Matrix());
               // (b) グラデーションパターンと画像を重ね合わせる。
               var reflectionData:BitmapData = new BitmapData(tw, th, false, 0x00000000);
               reflectionData.fillRect(rect, 0x00000000);
               reflectionData.copyPixels(target, rect, new Point(), alphaGradientBitmap);
               // (c) Bitmapに変換して、透過度を設定。
               reflectionBitmap = new Bitmap(reflectionData);
               reflectionBitmap.alpha = .85;
               return reflectionBitmap;
           }

このコードのポイントは(a)のグラデーションパターンを作成するところです。
Math.PIとは、円周率を表していて、Math.PI/2は90度を意味します。通常の座
標軸は、左から右にむかうので、Math.PI/2を適用した場合は、時計回りに90度
つまり上から下に向かって描画するように制御できます。またグラデーション
には、線状(LINEAR)と放射線状(RADIAL)があり、段々薄くなっていく鏡面効果
の場合は、線状を使います。
(b)で画像を重ね合わせますが、copyPixelsを使うと、重ね合わせる透過ビット
マップを指定できるので、便利です。最後に(c)で使いやすいようにBitmapData
に変換し、透過度を指定しておきます。背景を白に変更した場合など、透過度
を調整すると、お好みの鏡面効果にすることができます。

■鏡面効果を開始する
initLoaderの(e)で設定した、Imageの描画が完了したときに呼ばれるメソッド
を以下のように定義します。

           private function invalidateReflection(event:Event):void
           {
            _invalidatedReflection = true;
            invalidateSize();
               invalidateDisplayList();
           }

このタイミングでようやく鏡面画像を書いてよし、というタイミングになるの
で_invalidatedReflectionフラグをオン(true)に設定します。
その後、画面の再描画を即すために、invalidateDisplayList()を呼び出します。

■実際に描画する
updateDisplayListを修正して、ビットマップの描画を行います。

           override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Numbe):void
           {
               if(_content && _invalidatedReflection)
               {
                   var contentWidth:Number = _content.getExplicitOrMeasuredWidth();
                   var contentHeight:Number = _content.getExplicitOrMeasuredHeight();
                   // (a) 描画領域の初期化
                   _imageShape.graphics.clear();
                   // (b) オリジナル画像の描画
                   _imageShape.graphics.beginBitmapFill(_imageShapeBitmap);
                   _imageShape.graphics.drawRect(0, 0, _imageShapeBitmap.width, _imageShapeBitmap.hight);
                   _imageShape.graphics.endFill();
                   // (c) 鏡面画像の描画
                   var m:Matrix = new Matrix();
                   m.scale(1.0, -1.0);
                   m.ty = 2 * _imageShapeBitmap.height;
                   _imageShape.graphics.beginBitmapFill(_reflectionShapeBitmap, m);
                   _imageShape.graphics.drawRect(0, _imageShapeBitmap.height, _reflectionShapeBitma.width, _reflectionShapeBitmap.height);
                   _imageShape.graphics.endFill();
               }
           }

ビットマップを描画領域に書き出すには、graphicsオブジェクトを使用します。
graphicsオブジェクトはShape上にベクター描画するためのプロパティです。
beginBitmapFillはビットマップで塗りつぶしを開始する、という宣言で、描画
範囲をdrawRectで決定します。graphicsオブジェクトで描画を終了する場合は、
描画の種類に関係なくendFillで終了します。
鏡面画像はそのままだと、オリジナル画像にグラデーションが重なっているだ
けの画像です。実際に鏡面効果に見せるためには、反転させて、位置を下げる
必要があります。(c)ではMatrixクラスを使って反転させています。画像の反転
など3D効果を出すのには、行列計算を行う必要があります。Matrixは表示オブ
ジェクトの回転、拡大縮小、平行移動を行列を使って計算することができます。
今回のケースは単純に反転するだけなので、拡大縮小(scale)メソッドを使いま
す。なぜ反転するのに拡大縮小?という疑問があるかもしれません。なぜなら
鏡面効果を考えてください。画像を180度回転させると左右が逆になります。
するとその後左右反転を呼ばなければなりません。これでは二度手間ですね。
つまり単純に反転させる効果はscaleメソッドを使い実施します。上下反転は
scale(1.0, -1.0)、左右反転は scale(-1.0, 1.0)で実現できます。
行列計算というと難しいイメージしかありませんが、100x200画像を拡大縮小さ
せる場合は、四点[(0,0)(200,0)(0,100)(200,100)]で、x,yそれぞれをscaleで
指定された値でかけるだけです。つまりscale(1.0,-1.0)の結果は
[(0,0)(200,0)(0,-100)(200,-100)]となるので、y軸0の値を中心に画像が上方
向に向いていることがわかると思います。結果として上下反転したように見え
るのです。

■まとめ
今回だいぶ長文になってしまいましたが、Flexを使ったビットマップ操作につ
いて理解が深まったでしょうか?鏡面効果ができたら、やはりカバーフロー風
に表示させてみたいですね。この連載でもカバーフローを再現する方向にした
いと思いますので、今後も楽しみに待っていてください。
(きしだ)

[1] : Opera 世界で一番にAcid3満点を叩き出したブラウザー。W3Cのメンバー
      が多いことでも知られている。
      http://jp.opera.com/

[2] : Opera Backstage Tokyo
      http://my.opera.com/chooseopera-Japan/blog/2008/03/17/opera-backstage-tokyo-2008-4-10
      http://my.opera.com/chooseopera-Japan/blog/2008/03/28/opera-backstage-tokyo
      http://my.opera.com/chooseopera-Japan/blog/2008/04/14/opera-backstage-report
      http://my.opera.com/chooseopera-Japan/blog/2008/04/14/opera-backstage-tokyo

[3] : これまでのメルマガアーカイヴ
      第1回: http://www.ObjectClub.jp/ml-arch/magazine/209.html
      第2回: http://www.ObjectClub.jp/ml-arch/magazine/214.html
      第3回: http://www.ObjectClub.jp/ml-arch/magazine/228.html
      第4回: http://www.ObjectClub.jp/ml-arch/magazine/232.html
_______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E0012-5&choice=0
普通:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E0012-5&choice=1
イマイチ:
http://www.ObjectClub.jp/community/object_ml/estimate?vol=E0012-5&choice=2

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■ 
■
┗【アンケート】気になるシステム業界 ホントのところ

今週は「あなたのリーダーのリーダーカラーは?」のホントのところ。もう少
しで春イベント。『受託開発の極意』を手に取ってくださった方も、多いと思
います。ありがとうございます。
さて、本書の中では「リーダーのカラー」ということにも触れています。
読者の皆さんは、自分のチームのリーダーがどんなカラーのリーダーなのか考
えてみてください。
それぞれのリーダーの特徴と関係構築は『受託開発の極意』に紹介されていま
すよ。(http://www.amazon.co.jp/exec/obidos/ASIN/4774134538/xpjp-22)

  【バリバリ型】事前の計画とそれに伴った意思決定を好む。以外に慎重。
     http://www.ObjectClub.jp/special/kininaru/vote?vol=197&choice=0
  【サクサク型】その場のすばやい意思決定を好む。軽やかな行動が特徴。
     http://www.ObjectClub.jp/special/kininaru/vote?vol=197&choice=1
  【よしよし型】事前計画を立てるが重要な場面ではメンバーの意見も取込む。
     http://www.ObjectClub.jp/special/kininaru/vote?vol=197&choice=2
  【ふむふむ型】ほとんどの場面でメンバーの意見を大切にする。
     http://www.ObjectClub.jp/special/kininaru/vote?vol=197&choice=3
  それは秘密です。
     http://www.ObjectClub.jp/special/kininaru/vote?vol=197&choice=4
  ちょっと語らせて!
     詳細をこのメールに返信ください!!

アンケート結果はオブジェクト倶楽部サイト上にて公開します。お楽しみに。
なお、前号「新入社員に、はじめに教えることは?」の結果は公開中。ぜひご
覧下さい。
⇒http://www.ObjectClub.jp/special/kininaru/vol196/PlonePopoll_results2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
■
┗編集後記

こんにちは、編集人です。なかなか着手できない仕事に着手する方法というコ
ラムを読みました。「なかなか着手できない仕事」にはいくつかの傾向があっ
て、そのうちのひとつは「すぐには結果がわからない」そうです。確かに自分
がどのぐらい頑張っても、手ごたえが無いのではやる気もなくなりますね。
ひとつの対策方法として、作業を細かい単位にしてゴールを作るという内容が
書いてありました。例えば、部屋を片付けるというものを「クローゼットの一
段目を見やすく収納する」といった感じです。今年のゴールデンウイークは、
たまっていた「なかなか着手できない仕事」に着手する予定です。この考えを
活かしてぜひ着手してみようと思います。(上田雅美)

今週の強引な一言
*** 「君!ブライトさんの言う通りよ。
          寝るのもパイロットの仕事のうちですよ」(マチルダ)***
プロジェクトの納品間際になって、しばしば徹夜などをせざるを得ないことが
あったりするものですが、その一日だけならいざ知らず、進捗をカバーするた
めに睡眠時間を減らしても、体を壊してしまっては元も子もありません。
同様に体調不良を押して出勤しても、結局チームの足を引っ張るようなことに
なるようでは意味がないでしょう。
読者の皆さんは、自分の力を充分に発揮できる、そしてそれを継続することを
可能とするペースで仕事をしていますか?(dot.)
出典 : 機動戦士ガンダム 第4話

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
● ご意見、ご感想は         ⇒このメールに返信ください
〇 配信中止、アドレス変更は ⇒http://www.ObjectClub.jp/community/object_ml/help/
〇 免責事項、過去の記事は   ⇒http://www.ObjectClub.jp/community/object_ml/
■ 発行:オブジェクト倶楽部 ⇒http://www.ObjectClub.jp/
Copyright (c)2003-2008 オブジェクト倶楽部. All Rights Reserved.
powered by Eiwa System Management, Inc.