Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 2/248: 1 2 3 4 5 6 7 8 9 »

nsIFocusManagerを使ってウィンドウを最前面に持ってくる方法 - Jun 24, 2011

Firefox上でいくつかのサブウィンドウを開いていて、それらのウィンドウすべてがワンセットで他のウィンドウより前に出てきていて欲しい場面、というのがある。

例えば、GIMPはツールボックス等が複数のウィンドウにばらけている。これがもし、画像を編集するウィンドウにフォーカスしたらツールボックスのウィンドウがその背後に隠れてしまうという風になっていると、まるで作業にならないだろう(古いバージョンのGIMPをWindowsで使った時にはそんな風になってて頭を抱えた記憶がある)。

また、そういうワンセットで表示されていて欲しいウィンドウ達が、同時に起動している他のアプリケーションのウィンドウの前と後ろにそれぞればらけてしまうというのも、使う時に地味にうざい。

Firefoxの上で、拡張機能が開くウィンドウでGIMPのウィンドウ群のような振る舞いをさせるにはどうすればよいのか。このエントリでは2つの方法を紹介する。

まず1つ目。nsIXULWindowインターフェースのzLevelプロパティを使うと、Firefoxのプロセスが開くウィンドウの重ね合わせの順序をある程度制御する事ができる。一番単純なやり方は、ウィンドウを一時的に最前面表示に切り替えて、その後すぐに元に戻す、という方法だろう。

var XULWindow = window
                .top
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIWebNavigation)
                .QueryInterface(Ci.nsIDocShellTreeItem)
                .treeOwner
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIXULWindow);

var originalZIndex = XULWindow.zLevel;
XULWindow.zLevel = Ci.nsIXULWindow.highestZ;
window.setTimeout(function() {
    XULWindow.zLevel = originalZIndex;
}, 0);

ただ、仕様上の制限のため、この方法はWindowsでしか使えない。少なくともUbuntu 10.04のGnomeでは機能しなかった。

代わりに考えられるもう1つのやり方が、フォーカスを使うやり方だ。単純に考えても、window.focus()でウィンドウにフォーカスを与えると、強制的にそのウィンドウを最前面に持ってくる事ができる。

しかしこの方法にも問題がある。普通にwindow.focus()すると、例えばそのウィンドウの中の特定のテキストボックスにフォーカスしていたとしても、そのフォーカスが失われてしまう事になる。

この問題を回避するには、Gecko 1.9.2/Firefox 3.6から導入されたフォーカスマネージャを使わないといけない。具体的には以下のようにする。

var FocusManager = Cc['@mozilla.org/focus-manager;1']
                   .getService(Ci.nsIFocusManager);

// 現在フォーカスされている要素を取得する。
// 第1引数:検索する最上位のDOMWindow
// 第2引数:再帰的な検索を行うかどうかのフラグ(trueを渡す)
// 第3引数:その要素が含まれているフレームのDOMWindowを
//          受け取るためのスロットとなるオブジェクト
var focusedWindow = {};
var focusedElement = FocusManager.getFocusedElementForWindow(window, true, focusedWindow);

// 現在のフォーカスが何によって与えられたかの情報を取得する。
var reason = FocusManager.getLastFocusMethod(focusedWindow.value);

// フレームにフォーカスする。
focusedWindow.value.focus();

// フォーカスされていた要素がある時は、その要素にもフォーカスする。
if (focusedElement) {
    // フォーカスを与える時に、スクロール状態等に変更を加えないように指定する
    let flags = Ci.nsIFocusManager.FLAG_RAISE |
                Ci.nsIFocusManager.FLAG_NOSCROLL |
                Ci.nsIFocusManager.FLAG_NOSWITCHFRAME |
                reason;
    FocusManager.setFocus(focusedElement, flags);
}

こうすれば、Linuxでも要素のフォーカス状態を失わせずにウィンドウを最前面に持って来れる。ウィンドウのフォーカスを動的に切り替えるため、その都度各ウィンドウが画面上でぺかぺか点滅してしまう(一瞬だけフォーカスされて、その直後にフォーカスが失われるため)、というデメリットはあるが。

js-ctypesで期待した通りにガーベジコレクトされてくれないから自分でmalloc/freeする - Mar 27, 2011

最初に要点だけまとめておくと、

  • js-ctypesを使う時は、JavaScriptのコード側では基本的にメモリの管理のことは考えなくてもいい(ガーベジコレクト任せにしていい)事になってる。
  • しかし実際使ってみると、JavaScriptからjs-ctypes経由で自分でmalloc/freeしないとどうにもならないという場面があるみたい。
  • なのでJavaScriptからjs-ctypes経由でmalloc/freeする方法とその実例を紹介する。

という話です。

続きを表示する ...

64bit整数を使わないという、js-ctypesの最適化ノウハウ - Mar 27, 2011

先に結論だけ書くと、

  • js-ctypesでCのライブラリから帰ってきた64ビット整数を32ビット整数2つで代用できる場面では、32ビット整数にしておいた方が何倍も速くなることがある
  • ctypes.uint32_tとctypes.unsigned_longが同じ意味になる場合(Win32/Win64など)はctypes.uint32_tを使った方がいい

という話です。以下、実際にどういうケースでこれが役立つかの説明です。

続きを表示する ...

js-ctypes - Mar 20, 2011

js-ctypesはFirefox 3.6から利用できるMozillaの独自の機能で、平たく言うとC言語の実装の中で定義された関数をJavaScriptから呼べるようにするという物。Pythonにctypesという機能があって、それのJavaScript版がjs-ctypes。

Firefox 3.6(Gecko 1.9.2)ではできる事の制限が厳しかったので使えるケースがあんまり無かったようなんだけど、Firefox 4(Gecko 2.0)では構造体がサポートされたので一気に使える場面が増えた。らしい。

システムモニターをFirefox 4に対応させなきゃねと思ってたんだけど、Compartmentがどうとか色々変更があったのを全部調べてたら絶対自分の手に負えん!!と思ったので、いっそのことjs-ctypesで実装すりゃいいんじゃね? と思って、試行錯誤しながらやってみてる。試行錯誤の様子はリポジトリを見るとバレバレです。

js-ctypesのいい所:

  • コンパイルしなくていい。SDKやらビルド環境やらを整えるのに苦労しなくてもいい。
  • 単にバイナリを用意できてないだけで、その環境でバイナリをビルドしさえすれば大丈夫なのに……って場合には、多分そのまま動く。(動かない場合もある)
  • CとJavaScriptの境界で動作するコードで考えなきゃいけなかった諸々の事(JavaScriptのコンテキストがどうだとか、nsIVariantを経由したりJSObjにしたりとか、いろんな事)を考えなくてもいい。

困った所:

  • 結局はCなので、C言語が分かってないとどうしようもない。(僕はjs-ctypesでちょっとC言語への理解が深まりました……)
  • Cでの開発だったらヘッダファイルをインクルードすればそれでいいという場面でも、js-ctypes用に構造体の定義をJavaScriptで全部書き直さないといけない。
  • 取得した値が数値になってると思って「+」演算子で計算しようとするとハマる。数値を返すような関数でも返ってくる値はjs-ctypesによってラップされたオブジェクトなので、「+」演算子で繋げると文字列連結になってしまう(「-」などの、数値型に暗黙のうちに変換する演算子であれば問題は起こらない)。
    • 必ずparseInt()する、みたいな癖を付けとくとハマらなくていいと思う。
  • JavaScriptの書き方が悪くてJITされてないせいもあるのかもしれないけど、ループが遅くいからか、Cで書くよりずいぶんパフォーマンスが落ちる場面がある。メモリ消費量の計算だけでCPUを20%近く使っちゃうことになったりとか……

JavaScriptでFirefoxをクラッシュさせたかったらjs-ctypesでメモリ破壊とかやると手っ取り早いですよ! と、数え切れないほどFirefoxをクラッシュさせて思いました。

JSDeferredを小さくする - Feb 27, 2011

JSDeferredは非同期処理の制御に特化しててサイズも小さくて素敵な軽量ライブラリだ!と僕は思ってるんだけど、世の中を見回してみると「軽量ライブラリ」って言われてる物は3KB未満とかそういうのが結構あるようだし、jQueryも1.5.1のminified版は28KBって書いてあるし、そうなるとjsdeferred.jsのコメント付き版が0.3.4で19KBというのは「軽量」と呼ぶにはひょっとしてちょっとでかいのかな……という気がしてきた。

なので、JS MinifierとかPackerとかそういう風なやつでどれくらい小さくなるのか実験してみた。

/packer/はそのままだと構文エラーで動かなくなってしまった。}Deferred. って部分が7箇所あってこれがエラーになってるので、全部 };Deferred. に置換(Base62圧縮後だと }4.};4. に置換)したら一応エラーは出なくなった。/packer/の構文解析が貧弱なせいっぽいので、JSDeferredの側で問題になる所にあらかじめセミコロンを入れておけば、この問題は無くなるっぽい気がする。……と書いたからか、ちょよんごさんが対応してくれた。ありがとうございます!

あと、closure-compiler を通すと 2668bytes でした (jsdeferred のレポジトリで rake すると URL が出るようになってます)というアドバイスも頂いたので早速Closure Compilerにかけてみた所確かに小さくなったのですが、シンボル類まで全部失われちゃってこれ単体だと他のスクリプトと組み合わせられないのが残念ですね。(Closure Compilerは他のスクリプトも全部合わせて一緒にコンパイルして使うのが前提ってことなんだろう)

Excelの「AA」とかのカラム名とカラム番号の数値を相互変換する - Feb 15, 2011

96桁目のセルに所定の値が入ったCSVを作る、みたいな事をやらなきゃいけなくなったんだけど、GnumericにしろExcelにしろカラム名が数字じゃなくてA, B, C, ... Z, AA, AB, ... ZZ, AAA, ...というヘンテコ表記になってるからどこのセルに値を入れればいいかわかんないよウワァァァァン!!!! となったのでJavaScriptで解決した。


var input = prompt('input number or column name');
if (!input) return;

var symbols = 'abcdefghijklmnopqrstuvwxyz';
var result;
if (/^[0-9]+$/.test(input)) {
   input = parseInt(input);
   result = [];
   while (input > 0) {
     result.unshift(symbols.charAt((input - 1) % symbols.length));
     input = Math.floor((input - 1) / symbols.length);
   }
   result = result.join('').toUpperCase();
}
else {
  result = 0;
  input = input.toLowerCase().split('').reverse();
  for (var i = 0, maxi = input.length; i < maxi; i++) {
    result += (symbols.indexOf(input[i]) + 1) * Math.pow(symbols.length, i);
  }
}
alert(result);

カラム名→カラム番号の計算方法は分かったけど、頭が悪い僕にはカラム番号→カラム名の計算式が分からなかったので、検索して出てきたエクセルの1000列目は ALL - つまみ食うのアルゴリズムを丸パクリした。阿呆ですんません……

なんでそこで詰まったかっていうと、単純な26進数の変換ではうまくいかなかったからなんですよね。A==0、B==1という感じで26進数として扱うと、26==Zで27==BAになるんだけど、実際は繰り上がった後はBAじゃなくてAAにならなきゃいけない。そこの所を考慮した計算を多分簡単なループで実現できるとは思ったんだけど、頭が働かなくて無理だった。

ツリー型タブとマルチプルタブハンドラのイベント周りのAPIをちょっと変えた - Jan 11, 2011

Tree Style TabMultiple Tab Handlerを更新した。

今回のアップデートでも例によってMinefield対応のための修正をちょっとずつ入れてるんだけど、その中で1つ、なかなか気付いてなくてハマってた所があった。それはカスタムイベントを使ってた部分。

DOM2 Eventsではこんな風にして任意のDOMイベントを発行できる。

var event = document.createEvent('Events');
event.initEvent('MyCustomEvent', true, false);
event.status = 'current status';
event.tab = tab;
gBrowser.dispatchEvent(event);

受け取る側はこれをaddEventListener()で登録したリスナで拾うようにすれば、各々のモジュールの結合度合いを弱められる。なので僕は自分のアドオンでも積極的にこれを使ってる。

が、これがMinefieldでは使えなくなってた。

多分Compartment(JavaScriptのメモリ空間をスクリプトのオリジンだったかウィンドウだったかごとに分ける機能)が入ったからだと思うんだけど、Chrome URLのスクリプトで上記の例のように追加した任意のプロパティを、JavaScriptコードモジュール側のイベントリスナで参照できなくなってた。上記の例だと、捕捉したイベントのevent.tabundefinedになってしまってて、こういうやり方で情報を引き渡してた部分がエラーになってしまってた。wrappedJSObjectundefinedなので、生のオブジェクトを辿る事もできなかった。

MDCにある任意のカスタムイベントを実装する方法の詳しい説明によると、XPIDLでインターフェースを定義してC++で実装を書いてという事をやれば、今までと完全に同じAPIで任意のイベントを発行できるようなんだけど、それはちょっと重たすぎてやる気になれない。

なので次善の策として、汎用のデータを受け渡すためのイベント型があればそれを使おうと思って検索したら、Firefox 3以降ではDataContainerEventとかMessageEventとかの型のイベントが利用可能になってたという事を知った(今更)。

渡すデータがJSON文字列化できる物なら、WebSocketで定義されてるMessageEventがいいっぽい。

var event = document.createEvent('MessageEvent');
event.initMessageEvent('MyCustomEvent', true, false,
  JSON.stringify({ status : 'current status',
                   tab : tab.getAttribute('id') }),
  '', '', null);
gBrowser.dispatchEvent(event);

受け取った側はJSON.parse(event.data)でデータを復元できる。

DOM要素とかも渡したいなら、nsIVariant型でデータを受け渡せるDataContainerEventを使うしか無さげ。

var event = document.createEvent('DataContainerEvent');
event.initEvent('MyCustomEvent', true, false);
event.setData('status', 'current status');
event.setData('tab', tab);
gBrowser.dispatchEvent(event);

受け取った側はevent.getData('tab')のようにしてデータを取得できる。

ということで、プロパティアクセスにしてた所は全部DataContainerEventのやり方を使うように直した。ただ、後方互換性のためにプロパティアクセスでも情報はセットしてあって、同じCompartmentのスクリプトからなら多分今まで通りのやり方でも情報を受け取れると思う。

あと、DataContainerEventの存在を知る前に、MDCのドキュメントに書いてあった「イベント名がnsDOMで始まってない物は任意の情報は受け渡せないよ」という部分を読んでイベント名を「nsDOMTreeStyleTab...」という感じに変えていて、実際これでちゃんと動くようになった部分もあったんだけど、結局DataContainerEventにするようにしたからこれは結果的には余計だったかもしれない……

Jetpackを読み解く - Nov 10, 2010

Developers Conferenceでの発表向けの内容に盛り込めそうにない話を書いていく。

話のテーマを決めるにあたって、とにかく最初は1つJetpack SDKでアドオンを書いてみようと思ったんですよ。

でも、「こう書くと動きますよ」って言われてもなんだか信じられなかったというか、どういう経路でどういう風にしてそのコードが読み込まれるのか分からなくて、スクリプトの書き方次第じゃ他のコードに悪影響を及ぼしたりすることもあるんじゃないのか?(prototoype.jsのObject汚染みたいな感じで)とか、名前空間の衝突は大丈夫なのか? とか、そういうどーでもいい所が気になって気になって、仕組みが分からないまま使うのは怖いと思った。何をやってよくて、何をやったら駄目なのか、というのが分からないのが怖かった。

その境目を見極めたくて、Jetpack自体の成り立ちを探ってみたのですよ。

特に謎だったのが、他のモジュールを読み込むrequire()。これが一体どこで処理されているのか。main.js(Jetpackでアドオンを作る時の主たる実装になるファイルの固定の名前)もどこかからrequire()されているのなら、require()の実装を見たら謎が解けるんじゃないかなーと思った。

  • 核になるのは packages/jetpack-core/lib/securable-module.js の内容。Jetpackで頻出のexportsrequire()はここで定義されている。
    • コードを見ると、CommonJS風のやり方だけでなく、JataScriptコードモジュール形式の書き方(EXPORTED_SYMBOLSを使うやり方)にも対応してるみたい。
  • コードを追っていくと、最終的に Components.utils.evalInSandbox() が呼ばれていることが分かった。ライブラリのモジュールもmain.jsも全部これで実行される。
    • ということで、JavaScriptの名前空間の中での事に関してはどんな無茶をしても大丈夫そうという事が分かった。
  • もうひとつ、packages/jetpack-core/lib/cuddlefish.js も重要っぽい。
    • Jetpack自体の組み込みのライブラリでしょっちゅう使われてるユーティリティっぽいモジュールであるところの require("chrome") の実態が、これ。
    • Cuddlefish Labというアドオンの形で導入することもできるみたい?
    • Labs/Jetpack/JEP/28に、詳しい事が書かれてる。

Jetpackとは、この基本的な仕組みに基づいて、個々のモジュールの名前空間を分け、それらを安全に連携できるようにしたもの。と言える。MozLabでmodule_manager.jsというものが過去に使われていて、それを想起させられた。

module_manager.jsはJavaScriptコードモジュールが無かった頃にJavaScriptそのものの言語仕様を超えた所で高度なモジュール化を行おうとしていたらしく、渡されたモジュールの名前からパスを生成してファイルを読み込んでサンドボックス内で実行してそのグローバルオブジェクトを保持し続けて……ということを普通のJavaScriptの機能とmozIJSSubScriptLoaderでやってた。Jetpackの仕組みはそれのずっとスマートなバージョンなのかなと思った。

今までの開発手法しか知らなくてJetpackがさっぱり分からないという僕みたいな時代後れの人でも、securable-module.jsとcuddlefish.jsを起点にすれば、他のモジュールも無理なく読んでいけるんじゃないだろうか。

未だにXBLを使うことを避けられない場面 - Oct 22, 2010

XBLはアドオン同士の衝突の原因になりやすい。だからXBLはあまり使わないように僕はしてる。

XBLを使うと、DOMノードにgetterやsetterになってるプロパティを定義したり、独自のメソッドを追加したりできる。でも、それらはJavaScriptのテクニックで代用できないこともない。JavaScriptのレベルで目的を達成するやり方として、僕は最近よく、こんな設計をしてる。

function MyController(aNode) {
  this._node = aNode;
  this.init();
}
MyController.prototype = {
  get property() {
    ...
  },
  set property(aVaule) {
    ...
  },
  method : function() {
    ...
  },
  init : function() {
    this._node.addEventListener('...', this, false);
    ...
  },
  destroy : function() {
    this._node.removeEventListener('...', this, false);
    ...
  },
  handleEvent : function(aEvent) {
    ...
  }
};

var node = document.createElement('box');
node.controller = new MyController(node);

かなりの部分はこういったやり方で目的を達成できると思う。ツリー型タブなんかもこれに近い実装になってる。

ただ、オートコンプリートのテキストボックスの挙動を変えるだとかの、本体で定義されている物を置き換える場面では、たまにこの方法だけでは不十分なことがある。例えば<textbox type="autocomplete" />な要素のmaxDropMarkerRows<panel type="autocomplete" />な要素のoverrideValueやなんかはreadonlyなプロパティとしてXBLで定義されてしまっているので、これらが返す値を変えたいと思うと結構厄介な事になる。

XBLを使わないでサクッと済ませようとすると、__defineGetter__()を使う方法がまずは思い浮かぶ。Firefox 3.0以降ではDOMノードに対して__defineGetter__()を使えるので、上記の例のコードのinit()あたりでそれを使ってやるという感じだ。実際、XUL/MigemoではoverrideValueで任意の値を返すためにそうしてる。

でも、この方法はできれば使わない方がいいのかもなと思ってる。そう思ったきっかけは、同じようなことをやるコードの自動テストを書いていた時。setUpとtearDownで毎回ウィンドウを開いたり閉じたりとやってると時間がかかってしょうがないからUxU組み込みのフレームにページを読み込ませて……という風にしてみたら、セキュリティの制限に引っかかってしまった。object.__defineGetter__(name, getter)objectgetterの属してる名前空間が違うと、Illegal valueとか言われてエラーになってしまった。それでTrunkでの__defineGetter__()の実装を見てみたら、この両者のコンパートメントが違う場合はゲッタの登録を拒否するような設計になってた。こういうセキュリティの制限を回避してreadonlyなプロパティの働きを置き換えようと思ったら、どうもやはり、XBLを使うしかないようだ。

そもそもなんでoverrideValueがreadonlyなんだよ、なんで書き換え可能なただのフィールドになってないんだよ、って思って来歴を調べてみたら、nsIAutoCompletePopupインターフェースのoverrideValue昔のオートコンプリートの実装におけるgetOverrideValue()メソッドがその祖先で、当時のコードには「こいつの働きを変えたかったらXBLでオーバーライドしろ」ってコメントが書いてあった。今のFirefoxのオートコンプリートの実装にはこのコメントがなかったので、なんでreadonlyになってるんだよという不満しか抱きようがなかった。getXXXとなってたメソッドをプロパティの形に置き換えるなら、確かにそれはreadonlyになるだろう。

でもどうせプロパティに変えたんだったらwritableにしたってよかったはず。ほんとに、何でこんな設計にするんだろう……

可変フレームなアニメーションを管理するためのライブラリをmozRequestAnimationFrame/MozBeforePaintに対応させた - Sep 01, 2010

JavaScriptでアニメーション(モーショントゥイーンなど)をやろうと思うと、setTimeout()とかsetInterval()とかのタイマーを使うことになる。でもタイマーを複数個同時に走らせるのはリソース的に無駄だしオーバーヘッドが大きいせいでアニメーション効果ががたついてしまうようになったりするので、複数のアニメーションを同時に進行させるなら、1つのタイマーで複数のアニメーションを同時に処理した方がいい。

というわけで、そのためのライブラリをだいぶ前に作った。これは実際にツリー型タブ等で使ってる。以下のようにすると、タイマーの開始とか停止とかをヨロシクやってくれる。

var animationManager = window['piro.sakura.ne.jp'].animationManager;
// JavaScriptコードモジュールとして読み込むなら
// Components.utils.import('resource://myaddon-module/animationManager.js');
// で animationManager がエクスポートされる

var tab = gBrowser.selectedTab;
var task = function(aTime, aBeginningValue, aTotalChange, aDuration) {
       // aTime:アニメーション開始時点からの経過時間(ミリ秒)
       tab.style.marginLeft = (aBeginningValue + (aTime / aDuration * aTotalChange))+'px';
       return aTime > aDuration; // trueを返すとその時点でアニメーション終了
     };
animationManager.addTask(
     task, // アニメーションの処理そのものとなる関数
     parseInt(getComputedStyle(tab, null).marginLeft), // aBeginningValue:初期値
     50, // aTotalChange:変化量
     250 // aDuration:アニメーションにかける時間(ミリ秒)
   );

この例だとmargin-leftが今の値から50増加するアニメーションだけど、変化量の指定をマイナスにすればそれだけで、今の値からmargin-leftが50減るアニメーションになる。(ちなみに、アニメーションの処理となる関数が受け取る引数の形式がなんでこうなってるのかについては、「高速な環境ではたくさん描画していいけど、低速な環境だと再描画を減らしてほしい。とにかく、1回のアニメーションは決まった時間の中できちんと終わらせたい。」という可変フレームなアニメーションをやりやすくするためです。)

既に動いてるアニメーションを中止する時は、登録した関数をremoveTask()に渡す。

animationManager.removeTask(task);
// すべてのアニメーションを中止するなら
// animationManager.removeAllTasks();

中止ではなくてアニメーションを一時停止→再開させたい場合は、こう。

animationManager.stop(); //停止
// ...何かの処理...
animationManager.start(); // 再開

という感じのライブラリなんだけど、これを最近mozilla-centralに入った新しいアニメーションのためのAPIに対応させてみた。APIとしての変更は、addTask()の最後の引数にDOMWindowを受け取るようになったという点のみ。

animationManager.addTask(
     task,
     parseInt(getComputedStyle(tab, null).marginLeft),
     50,
     250,
     window // アニメーションを行うウィンドウ
   );

リンク先で紹介されているmozRequestAnimationFrame/MozBeforePaintが利用できる環境ではそれを使用して、そうじゃない時は今まで通りsetInterval()で処理する。ライブラリを使う側のコードは、Firefoxのバージョンの違いを意識する必要は全く無い。ただ、APIを生で使う時に比べるとオーバーヘッドがあるから、新APIのメリットぶちこわしかもしんない。

リンク先のエントリを見た感じでは、理屈としては一般的な可変フレームレートのアニメーションの考え方に基づいているみたいなんだけど、DOMのイベントをトリガーにしないといけなかったり次のフレームを描画するためにいちいちメソッドを呼ばないといけなかったりというのは煩わしいと思ったので、せっかくだからライブラリ側で面倒を見るようにしてみた。

Page 2/248: 1 2 3 4 5 6 7 8 9 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき