[iPhone/iPad]WebApp制作における読み込み時間/オフライン問題

2011
05.18

皆さんこんにちわ、最近随分日が長くなったなぁとしみじみ思います。

そして随分書きかけのエントリーが溜まって来たなぁと思います。

消化しないとただの豪華なオンラインメモ帳になってしまいます、これはいけません。

 

そう言う事も踏まえてなお、単発ネタです。

iPhone / iPad をターゲットにした WebApp でネックになるのは読み込み時間とオフライン時の挙動です、普通にブラウザアプリを作る感覚で行くと下記のような問題にブチ当たります。

  • ページ遷移の度に読み込んでたらストレス溜まる
  • かと言って全部最初に読み込んでおいてメモリに展開すると色々と苦しい
  • そもそもオフラインだとページ遷移とか非同期通信自体不可能じゃない

ネイティブアプリは全てローカルにリソースを置く事で回避出来るのですが、Web ブラウザを使っている以上このような問題が起こります。

 

困りました、調べました、解決しました。

 

なんの事は無い、iOSAndroidWEB Database API を実装しているじゃないか。良く考えると双方 Webkit 系だもんね、今更気づいたのかよ!と言わざるを得ません。てへ。

この API はブラウザの JS から双方のネイティブアプリを触っている方はお馴染みの SQLite3 へとアクセスする事が出来ます、つまり始まる前に全部ローカルにデータを保存しておく事が出来ます。ちょっと試した事が無いのですが blob 型が有るのでバイナリも突っ込めるはず。

そしてもう1つの問題、オフライン時にページを開こうとしたりリロードしたりしようとすると「ページを開けません。インターネットに接続していません。」みたいなエラーが出るのですが、これも .manifest を使えば回避可能です。

オフラインだとこうなります

これは強力なキャッシュ機能で、指定したファイルを全てローカルに保存して次回からはとにかくここから読み出すようです。中身を更新したい時は .manifest の中身の文字を1文字でも変えれば再構成されるようなので、ページの要素を読み込む前に .manifest のチェックが先に実行されているみたいです。

要するにバージョン管理をきちんと行い、.manifest にはそのバージョン名を入れておけば常に最新の状態をユーザーに提供出来ると言う訳ですね。

 

さて、これで…かなりネイティブアプリに迫る事が出来るようになったハズです。

思っていた以上に私は WebApp について解っていなかったのがショックですが、これで同じ土俵には上がれたと思うので益々精進したいと思います。

 

それではまた。

 

 

[iPhone/iPad]WebAppのクラス設計について

2011
05.17

 

皆さんこんにちわ、お久しぶりです。

GW 以降バタバタしておりましたが一段落したと言いたい所ですが、この業界の三大職業病「肩こり」「腰痛」「イボG」のウチ、堂々の二冠達成と言う偉業を現在進行形でございます。

 

ちょっと単発ネタです。

先週は在宅勤務で引きこもっていたのですが、何もただ単に引きこもっていた訳ではありません。

仕事や家事や PSP でミクさんを愛でる時間の合間をぬって、iPhone / iPad 用の WebApp の開発を行っていました。今回構築しているアプリのベース部分が完成して、初代 3G なんかも引っぱり出して来てニヨニヨとしていたのですが…ここからエフェクト系を山盛り入れるには、とてもじゃないけどメモリが足りない事に気づきました。

 

だって既にちょっと重いもん。

 

画像や音声ファイルのロードは最初からネックになる事は解っていたのですが、JS で生成しているオブジェクトと我らの味方の jQuery が重たくてしょうがないのです。

 

安定性を欠くようではリリースなど片腹痛い訳で、これはもう基礎部分から再設計を余儀なくされた状況です。

リソースをふんだんに使うタイプの WebApp 開発にあたり、今回解った事は下記。

  • jQuery は使わない方が良さそう
  • prototype 定義を最大限使わないとキツい
  • Ajax による リソースの loader 部分がかなりマゾい
  • ダイナミックな動きは全部 CSS3 で賄う

1つ目は単純にライブラリよりネイティブの方が早い、当然ですね。クロスブラウザ対策が必要ないのでそこまで恩恵がある訳では無いので外す方向で行こうと思った。
そうなると要素に対して CSS3 を適応させる部分は大丈夫なんだろうか、とかの不安が残る。

 

2つ目は調子に乗って何個かインスタンスを作っているとメモリがアワワな事になる、昔 prototype 汚染にトラウマ級の悪さをされて以来食わず嫌いになっていたがそんな事言ってられなくなった。
これは私の設計の甘さもあるのですが…ガベージコレクションを使う手もあるんだろうか。

 

3つ目は WiFi 環境なら余裕で無視出来るレベルなのですが、貧弱な 3G 回線だとメディアファイルの load 時間がかなりストレスになる。しかし全てのファイルを始めに読み込んでおくのは 3G や 3GS のメモリ量だと厳しい感じがするので、先読みアルゴリズムを極限まで詰めて解放/読み込みをこまめにやるべき…?
逆にキャッシュの限界量に合わせてリソース側に制限をかけるべき…?

 

4つ目は jQuery を解雇するなら当然変わりにアニメーションを担当するものが必要になる、これは使ってみた感想だけど CSS3 でアニメーションさせると jQuery の何倍も何十倍も綺麗に動くので他に選択の余地は無いと思った。
canvas を使う手もあるのだけど、html5 で組むからこそ意味があると思っているので FLASH 的な動き(むにゃむにゃ動く背景とか)の時だけ使うのが良いと思う。

 

世界的にまだまだ開拓途中のこの WebApp と言う世界、今後のスマートフォンの主力コンテンツとしての活躍が期待されているのでやり甲斐があって楽しいのですが…

 

WebApp は開発サイクルが短くて予算節約になりますよ!

 

と言う売り文句を言えるようになるまでが大変そうです、セオリーは俺が作る!ぐらいの気概は必要ですね。

 

それではまた。

 

 

[CSS] 立体的なレイアウトを組むコツ Vol.1(positionの基礎知識)

2011
04.29

Hello everyone.

なんだか海外の方からの反響が結構ある事に驚いています、私は英語の授業をサボり続けた事を今になって後悔しています。

返信とか凄い片言なんだけど大丈夫かな?

 

さて今回のコラムは、立体的なレイアウトを組むテクニックを2回に分けて紹介して行きます。

お勉強しましょう。

テクニックと言うよりコツですね、レイアウト構造を設計出来るようになれば事実上 html 上で再現出来ない2次元レイアウトなど存在しなくなりますので苦手な方は是非とも熟読して行って下さい。

 

さて、立体的なレイアウトと言えば外せないのが CSS の position プロパティです。

まずはこれをきちんと理解しましょう、特に positionrelativeabsolute はきちんと理解して使わないと何だか解らなくなって、要素が凄い所に飛んで行っちゃったりと収集がつかなくなるので、きちんと管理しておくのもポイントですね。

 

position プロパティの仕様
概要
static デフォルト値、何も指定しなかったらこれが指定されます。
何も指定していない状態なので toprightbottomleft などのプロパティは適応されません、イメージ的には背景に張り付いていると言うのが近い表現だと思います。当然ですが高さと幅を保持します。
relative 指定した要素を相対位置へ配置します、この相対位置の意味が良く解らないと言う話しは良く聞きますので後ほど図解します。
この値が指定されると toprightbottomleft のプロパティが有効になります、この時のイメージは身を乗り出していると言うのが近いと思います。これは高さと幅を取りながら位置をずらす事が出来るからです。
absolute 指定した要素を絶対位置へ配置します、これは relative と並べて書くと解りやすいので後ほど図解にて。
relative と同じく指定するとtoprightbottomleft のプロパティが有効になります、イメージ的には飛ばしている状態です。これは完全に任意の位置にずらすため高さと幅を放棄します。
この値には特徴があり、親のブロック要素に static 以外の値が指定されているとその親ボックスの左上を起点とするが、逆に static が指定されている(=何も指定していない)とウインドウの左上を起点として位置が決まります。
fixed 指定した要素を絶対位置に配置し、スクロールによる画面移動を無視してその場に留まります。
非常にユニークな値ですが、IE6 など諸問題があって積極的には使われていない印象があります。
有効になるプロパティやイメージも absolute と同じです、単純に一回決めた位置から動かないと言う事を覚えておけば良いでしょう。

 

relative と absolute の性質

それでは早速両者の性質について図解していきます、解り辛い文面を読むよりヴィジュアルを見て感覚を掴むのが良いでしょう。

 

inline 要素に relative(相対位置)を指定すると…

1
2
3
4
5
span {
    position: relative;
    top: 10px;
    left: 10px;
}

inline要素にrelativeをかけると

こうなります、赤いクロスの中心が起点となります。

要するに相対位置に配置すると言うのは static 状態(何も指定していない)の時に有るべき位置から◯◯px ずらすと言う事です、大きな特徴として高さや幅を保持すると言う点も見逃してはならないでしょう。図を見ると「どうですか?」の位置がずれていませんよね。

イメージとして身を乗り出していると比喩したのはこう言う理由からです、block 要素だともっと解りやすいです。

 

 

block 要素に relative(相対位置)を指定すると…

1
2
3
4
5
p {
    position: relative;
    top: 10px;
    left: 10px;
}

block要素のrelativeをかけると

相対位置=本来有るべき位置、から上と左 10px ずつずれた位置に block 要素が移動し、高さと幅は保持されるので foofoo の block は位置ズレを起こしません。結果、少し重なる形で表示されます。

 

 

inline 要素に absolute(絶対位置)を指定すると…

 

親要素に static が指定されている(特に何も指定していないデフォルト状態)場合

1
2
3
4
5
6
7
8
9
div {
    /* 特に何も指定していない */
}

span {
    position: absolute;
    left: 10px;
    top: 10px;
}

親要素がstaticの時にinline要素にabsoluteをかけると

親要素に対して何も指定していない場合や static を指定している場合、ウインドウの左上が起点になります。

ここで注目したいのが飛ばした時に残されたテキストです、緑色の部分が抜け落ちてテキストが前に詰められています。絶対位置に要素を飛ばした時はその高さや幅の情報を破棄します。

と言う訳で飛ばしていると比喩しました、もうそこには無いものとして扱われますからね。

 

 

親要素に static 以外が指定されている場合

1
2
3
4
5
6
7
8
9
div {
    position: relative;
}

span {
    position: absolute;
    left: 10px;
    top: 10px;
}

親要素がstatic以外の時にinline要素にabsoluteをかけると

対して今度は親要素に static 以外、今回は relative を指定してみました。

すると起点が親要素の左上になりますので、タイトルに少し被る感じにずれたのが解ります。

起点が変わるだけで、テキストは抜けた分が詰められているなど同じ挙動なのも確認出来ますね。

 

 

block 要素に absolute(絶対位置)を指定すると…

 

親要素に static が指定されている(特に何も指定していないデフォルト状態)場合

1
2
3
4
5
6
7
8
9
div {
    /* 特に何も指定していない */
}

p {
    position: absolute;
    left: 10px;
    top: 10px;
}

親要素がstaticの時にblock要素にabsoluteをかけると

ここまで来ると予想出来るようになって来ているのでは無いでしょうか?

例によって static 状態なのでウインドウの左上が起点、要素は高さと幅の情報を破棄するので foofoo のブロックは前に詰められます。

※飛ばした block 要素が伸びているのは単純に width が auto なので…同じ形のまま飛ばしたければ飛ばす要素の width も指定しておけば良いです。

 

 

親要素に static 以外が指定されている場合

1
2
3
4
5
6
7
8
9
div {
    position: relative;
}

p {
    position: absolute;
    left: 10px;
    top: 10px;
}

親要素がstatic以外の時にblock要素にabsoluteをかけると

そして最後は親要素を static じゃない状態にした時のサンプルです、起点が変わっているだけで foofoo の block は前に詰められていますね。

 

 

以上が実際にどう言う挙動をするかと言う実例を交えた解説です、html を作成していると思わぬズレ方や崩れ方に遭遇する事があると思いますが、そのおかしくなった理由にどれだけ早く気づけるかがとても重要です、だからこの知識もきっとあなたの役に立つ事でしょう!

 

さて、今回はここまで。

次回はこの知識を前提につまりこうすれば思い通りの結果を得られると言うテンプレ的方法や設計するコツを書きたいと思いますので、今の時点では…

 

へー、position ってこんな感じだったんだ。

 

ぐらいで良いです。

このコラムを完走して理解した時、あなたはきっと自由自在に立体レイアウトを組めるようになっているハズです。

 

それではまた。

 

ブラウザから100%の状態でPDFを開きたい時

2011
04.25

皆さんおはようございます、何やら朝の通り雨が凄かった大阪です。

さて、今回は単発エントリー。クライアント様より

 

PDF 開いた時に凄い大きく表示されるよ、100%で表示して欲しいよ!

 

との要望がありまして、反射的に adobe reader の設定でデフォ 100% にすれば良く無いかい?と思いましたが、IE みたいにブラウザ上で直接 PDF が開ける場合は原寸表示出来た方が良いですね。と言う訳で軽く調べてみた。

 

1
<a href="./hoge.pdf#zoom=100" target="_blank">PDFだよ</a>

 

href 属性の URL の最後に「#zoom=任意の倍率」これで行けましたね、取りあえず IE しかチェックしてないけど要望は IE だけだったのでこれで良しとしましょう。

そもそも Firefox とかだとダウンロードして adobe reader で開くから、それこそホントに設定して頂戴よとしか言えませんしね。

 

それではまた。

 

[IE7|IE8] jQueryのfadeIn/fadeOutした時にpng画像が変になる時のTips

2011
04.22

悪名高き IE6 がついに Yahoo さんからも干されてデベロッパー歓喜!となってから、それなりに時間が過ぎましたね。

あなたの会社では IE6 のサポート状況は如何なものでしょう?当社では Yahoo さんもこうしていますよ、せめて IE7 にしましょ?ね?ね?と言う地道な活動を続けて、それなりに効果が出ています。

実際 IE6 をサポートしなければ CSS がシンプルに書けたり、png のアルファチャンネルをプラグイン無しで描画出来…で、き…

 

出来てないじゃん!

 

と言う訳で今回は IE7 と IE8 で再現を確認したアルファチャンネルの描画バグをフィックスします、症状は下記のような感じ。

  • 普通に img 要素で描画する分には問題無い
  • 既に描画されている要素の opacity を弄るとアルファチャンネル部分が黒くなる

普通にサイトを作っていて、png ファイルの要素の opacity を弄るなんて事はまず無さそうですが、最近はスタイリッシュにファッファさせたくなるじゃないですか?マウスオーバーしたらメニューが、みたいな。

それをお手軽に使いたい時はなんと言っても jQuery の fadeIn / fadeOut ですよね、例えば fadeIn は要素の opacity を一旦 0 にしてから display:block 状態に、そこから opacity を 1 になるまで加算すると言う処理を勝手にやってくれます。

つまり opacity 弄っちゃってます、IE7 と IE8 はここにアルファチャンネルが含まれた png 画像が描画されていると残念な黒い何かが出てしまうと言う訳です。

M$さんは「png ファイルのアルファチャンネルに対応しました(笑)」って言ってたのにね。

 

それではサクッとフィックスしましょう、解決法は AlphaImageLoader を引き続き使う。これで良いと思います、IE 自慢の独自フィルターだし。そもそも IE しかこの症状出ないから、自己解決させるのが最上の手段でしょう。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
$(function() {
    if(navigator.userAgent.indexOf("MSIE") != -1) {
        $('img').each(function() {
            if($(this).attr('src').indexOf('.png') != -1) {
                $(this).css({
                    'filter': 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' +
                    $(this).attr('src') +
                    '", sizingMethod="scale");'
                });
            }
        });
    }
});

ページの読み込みが完了したらブラウザ判定、どうやら IE だなとなれば html 上の img 要素全てを each して、src 属性に “.png” が含まれていたら AlphaImageLoader をかける。

 

これで IE7 と IE8 で思う存分ファッファ出来るようになる、IE6 は多分これだと駄目だと思うけど。

Yahoo さんの非推奨ブラウザなので今回は無視する方向で、Yahoo さんいつもスケープゴートになってくれてありがとう。

 

それではまた。