Hatena::ブログ(Diary)

latest log このページをアンテナに追加 RSSフィード

2011-07-10

uupaa2011-07-10

HTML5の文字エンコーディングの判定は 512byte または 1024byte 以内までに

HTML5のWorking Draft(20110113)までは、文字エンコーディング判定の範囲はファイルの先頭512byte以内と定義されていました。

そのため、

<!DOCTYPE html>
<!--[if IE 8 ]><html lang="ja" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml" class="ie8"><![endif]-->
<!--[if IE 9 ]><html lang="ja" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml" class="ie9"><![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--><html lang="ja" xmlns:og="http://ogp.me/ns#" xmlns:mixi="http://mixi-platform.com/ns#" xmlns:fb="http://www.facebook.com/2008/fbml"><!--<![endif]-->
<head>

といった、546byteの文字列の後に

<meta charset="UTF-8">
<title>こんにちは!こんにちは!</title>

とやってしまうと、正しく判定されるのか? ちょっと危うい気がしてしまいます。

http://www.w3.org/TR/2011/WD-html5-diff-20110405/ に書かれているように、

現在では、「512byte」→「1024byte」に改訂されています。

この時期に登場した IE9 はどちらの仕様でビルドされているのでしょうか? ちょっと気になりますね。

また、IE10pp2 からは ↓ のようなコンディショナルコメントは利用できなくなります(スルーされます)。

<!--[if IE 8 ]> <![endif]-->

ここ大事ですので、忘れないようにしましょう。


2011-07-10追記

IE9.01 は 512byte なんだろうか、それとも昔のIEのように、もっと先まで読んで判別しているのだろうか? という所が知りたくて、EUC-JP なファイル等も作ってみたのですが、文字化けしている状態でユーザが正しいエンコードを指定しなおすと、それ以降エンコードのパターンを学習する(またはエンコードに利用するバリエーションが増える)ような動きがあるらしく(その動きもあって、こちらの予想とは違う結果が出てしまう)、なんだかモヤモヤしたままです。

添付画像は、IE9.01 で http://jp.msn.com を開き、エンコードを[日本語 (自動選択)] にしたら文字化けしたよ の図

2010-12-17

クリスマスツリーを iPhone でも見れるようにしたよ


f:id:uupaa:20101219000618p:image

ジェバンニ仕事で、http://koebu.com/event/xmas/2010/iPhone / iPad に対応させました*1

目からビーム出して頑張ってる最中のツイートまとめ

iOS では、ユーザアクションを伴わない、audio.play() やaudio.load() は機能しない。さらにpreloadとautoplay属性も無効化されている http://bit.ly/fmLf5y in Device-Specific Considerations

http://twitter.com/uupaa/status/15433471463784449

なんかね、PCブラウザのように、audio.play() 呼んでも audio.load() 呼んでも動かなくて、色々ググッたんだよね。

iOS でBGMは、そのままでは自動再生できないので、ユーザに画面をタッチしてもらう必要がある

http://twitter.com/uupaa/status/15433728247468035

この時点では、window.addEventListener("touchstart", function() {...}, false) でイベントかすめとって、その隙に色々やったらどうなんだろう? とかモヤモヤしてた

つまりiOSでは、なんとしても画面にタッチしてもらって、そのタッチイベントハンドラ内で、audio.load()を含めゴニョゴニョまとめてやってしまって、ある程度までオーディオデータの読み込みが進んだら(canplayイベントが発生したら)、play()で再生すればできるのかな?

http://twitter.com/uupaa/status/15434696645156864

いやいやいやいやいや… ソレ無理あるだろうと。この後思い直すわけですが。

クリスマスツリーをiPhone対応にするためにゴリゴリ書き直してる。

http://twitter.com/uupaa/status/15439252250697728

寂しさと空腹に負けてツイート

iOSの<audio>とPCの<audio>は別ものなので、状態遷移そのものも別。

http://twitter.com/uupaa/status/15501925092958209

ドーパミンドバ〜 した時のつぶやき

そもそも状態遷移が違う

クリスマスツリーのページを、PCブラウザ向けに組んだ時は、

  1. mp3ファイルの一覧をAPIで取得する
  2. 取得したmp3ファイルを裏で読み込み、再生可能な状態になったらプレゼントとして登場させる
  3. クリックで再生開始

といった流れで、状態を管理していたのですが、

Apple の技術資料 http://bit.ly/fmLf5y にも書かれているとおり、ユーザアクションを伴わない形で audio.play() や audio.load() を実行しても iOS では機能しないから、PC用サイトのUIを組む感覚でiPhone用サイト組むと全くダメなことが判明。

モバイルSafariで動かすために、

  1. mp3ファイルの一覧をAPIで取得する
  2. プレゼントとして登場させる
  3. クリックでaudio.load()を実行 canplayイベントを待ってaudio.play()で再生開始

という別の流れを作成する必要がありました。

また、AudioPlayerクラスをPCブラウザ用(XmasPlayer)とは別に用意(XmasMobilePlayer)することで、モバイルSafariでの音声の再生も可能になりました。

# uupaa.js にはOOP的なクラスを作る機能があります。

モッサリをサクサクにする(アニメーションを軽くする)

クリスマスツリーのページのプレゼントボックスは、uupaa.js の uu.fx() を使いアニメーションをさせています。

uu.fx() の本質的なコードは以下のように、style.left と style.top といったスタイル属性を定期的に書き換えるというものです。

function tick() {
  node.style.left = x + "px";
  node.style.top  = y + "px";
}
setInteval(tick, 12);

ただ、left や top をタイマーで書き換える方式では、雪を4つ降らせただけでモッサリになってしまい、とても人前に出せる状態にはありませんでした。

そこで、前々からやりたかった機能(CSS3 Transition) を uu.fx() に組込み、機能強化を行いました*2

http://code.google.com/p/uupaa-js/source/detail?r=994

uu.fx.moveIn(), uu.fx.shlink(), uu.fx.flare(), uu.fx.puff() で、モバイルWebKitなら WebKitTransform を利用するように

uu.fx(node, duration, { tx, ty }) を指定時に、モバイルWebKitなら WebKitTransform を利用するように

従来は、

アニメーションを作成しますが、

これからは、

するだけで、uupaa.js が動作環境を判断し、PCブラウザなら tx → left と解釈、MobileSafari なら tx → WebKitTransform:transitionX と解釈するようになります。

つまり、

// これまで
uu.fx(node, duration, uu.env.mobile ? { transitionX:100, transitionY:100 } : { left:100, top:100 })

   ↓↓↓

// これから
uu.fx(node, duration, { tx:100, tx:100 })

スッキリ!

あっそうそう

IEモバイルSafariで見るとクリスマスツリーが短くて、その他のブラウザだと長かったり、複数の音声を同時に再生してガヤガヤできたりします。

あと、MobileSafariの<audio>は、ボリュームいじれないみたいなので、声が聞こえない時は iPod アプリを起動して音量大きくすると聞こえるようになります。

Boy Meets Girl !!

*1iOS4.2 以上推奨です。OSが古いと <audio> 動かないかも

*2:この辺は改めて別のエントリで説明します

2010-10-30

IE9pp6 で section, nav, aside, header, footer 等をサポート

IE9pp6 では、 -ms-transform 以外にも、以下の HTML5 新要素をサポートしています。

<nav /> 
<article /> 
<aside />
<hgroup /> 
<header /> 
<footer />

2010-09-01

HTML5 Forms Slider Control (input type="range")

デスクトップアプリケーションで利用されているフォームコントロールの多くがブラウザでは利用できません。

これを改善すべく HTML5 Forms で フォーム部品が追加されましたが、例によりブラウザの実装が追いついていないため満足に利用できる状況にありません。

安心して利用できる UI が欲しいよ! ということで、とりあえずはスライダーコントロール ( <input type="range"> ) の実装から始めました。

f:id:uupaa:20100901031312p:image

http://uupaa-js.googlecode.com/svn/trunk/0.8/test/ui/slider.htm

あのライブラリやあのライブラリとは異なり、iPhone でも同じルック/フィールでサクサク動きますよ。

# Android は持ってないから、テストしてないよ

2010-08-31

HTML5 Forms の UI をどう実装したらよいか悩んでいます

HTML5 で新しく定義された <input type="range"> 等を JavaScript で実装しようとしたときに、元の input 要素と UI 要素を関連付けする方法で悩んでいます。

<input type="range"
       id="hogeid"
       class="hogeclass"
       value="50"
       min="0"
       max="100"
       onchcange="onchange(this)" />

といった要素があったときに、 div要素 と input type="hidden" に置換して、元の input type="range" 要素から引き継げる属性値を引き継いでしまえば良いんじゃないか? と

つまり、こんな感じにしてしまえばいいのかなと。

<div id="hogeid-ui"                ← 元のID + "-ui" で自動生成
     class="hogeclass-ui slider"   ← 元のCLASS + "-ui" で自動生成
     data-uuui="slider">           ← 付与
    <div class="slidergrip" />     ← スライダーコントロールのグリップ部分
</div>
<input type="hidden"               ← input type="range" を置換する要素
       id="hogeid"                 ← 元のID を引き継ぐ
       class=""                    ← 元のCLASS を引き継ぐ
       data-uuui="slider"          ← 判別用に付与
       style="display: none"       ← 付与(念のため)
       value="50"                  ← 元の属性値 を引き継ぐ
       min="0"                     ← 元の属性値 を引き継ぐ
       max="100"                   ← 元の属性値 を引き継ぐ
       onchange="" />              ← 元の属性値 は引き継がない

めんどくさいのがイベントハンドラの扱いです。

特に DOM Lv0 だと onchange="onchange(this)" のように this がありうるので、どうしたもんかなと。