慣性ドラッグの jQuery UI プラグインを書き直した

前に作った、要素のドラッグに慣性っぽい挙動をつける jQuery UI プラグインをだいぶ書き直した。
併せて、Web に上げたドキュメントもすっかり新しくしています。

jquery.ui.phantomDrag.js
http://ykhs.github.com/jquery.ui.phantomDrag/document/

これは、プラグインを実行した要素をドラッグすると mousemove みたいな頻度でカスタムイベントが発生するので、それに .bind() して値を取得することで、現在のマウス位置より遅れた位置の座標が手に入ったりするというものでした。
ふわっとした動きのスライダーなんかを作るときに便利です。

前の版のよくないと思ったところ

カスタムイベントにバインドして、座標の取得は jQuery.fn.data() を使うっていうところにかなり回りくどさを感じていました。

$('#element').phantomDrag();

$('#element').bind('phantomdrag-move', function (e) {
  console.log($('#element').data('x');
})

今の版のよくなったと思うところ

プラグインを実行するときにコールバック関数を指定するように変更しています。
上記と同じく mousemove 的な頻度でドラッグ位置の情報を取りたい時には step というコールバック関数があるので、それを指定。
そして第二引数で、ドラッグした際の位置に関する情報をオブジェクトで受け取るようにしました。

これで、少しシンプルになったんじゃないかと。

$('#element').phantomDrag({
  step: function (e, res) {
    console.log(res.currentX);
  }
});

ふわふわしたドラッグ挙動つけたいだけなのに、このカスタムイベントに .bind() してください。で、値は jQuery.fn.data() で取得してください。とか、どうもルーブ・ゴールドバーグチックだし、プラグインと利用者を繋ぐ窓口を利用者にコントロールできないレイヤーで煩雑に規定してしまってるのがよくなかったのでは、とか考えてる。

History.js メモ

HTML5 History API の polyfill として機能するライブラリ “History.js” を解釈してみた点についてのメモです。

balupton/history.js – GitHub
https://github.com/balupton/History.js/

スクリプトのロード方法については GitHub に置かれている README が充実しているので基本的にそちらを参照するのが良いです。
“Download & Installation” の項になります。

History オブジェクト

スクリプトをロードすると History オブジェクトが利用可能になります。ブラウザが提供する history オブジェクトとは大文字・小文字違いになっていて、History.js が提供する機能はこの History オブジェクトから利用します。

次に、たぶんよく利用するのではないかというメソッドなどについて。

History.pushState()

ブラウザの履歴エントリに新しい URL を加える事ができます。

HTML5 History API における history.pushState() と同じように、以下の引数を渡すことが出来るため history.pushState() と同じ使用感で扱えます。

  1. 第一引数: state object – popstate イベントオブジェクトの state プロパティへ渡すオブジェクト
  2. 第二引数: title – 遷移先の title
  3. 第三引数: URL – 遷移先の URL

history.pushState() に未対応のブラウザでは、このメソッドを実行した際に、URL の末尾に #hoge.html?&_suid=229 といったような location.hash が付与されます。たぶん popstate イベントの代わりに hashchange イベントを用いているためかと思われます。そんなことを述べている説明も README にありましたが、これで合ってるかな。

また、history.pushState() と比べると両者の pushState() 実行時には

  1. 第二引数の title が title 要素の値として反映される。
  2. popstate イベントの発火を伴う。

といった違いが見られました。

History.replaceState()

こちらも、History API における replaceState と同じで、URL を書き換えたいが、History.pushState() のようにブラウザの履歴エントリを残さずに行いたい。といったときに使います。

History.getState()

現在の履歴エントリの情報を取得します。返り値はオブジェクトになっており、様々な値が格納されているのですが実際に使うのは、data, title, url プロパティ辺りでしょうか。

History.pushState() を実行してブラウザの履歴エントリに格納した際の3つの引数と対応しており、渡した引数の第一引数は data. 第二引数は title. 第三引数は url を参照することでそれぞれ取得することができます。

statechange イベント

参照する履歴エントリに更新があった場合に送出されます。History.pushState() が実行されたり、それによって登録された履歴エントリをブラウザの「次へ」「戻る」機能で再度踏んだ場合とかですね。

History API が提供する popstate イベントとは別名の statechange というイベント名になっています。

History.Adapter.bind / History.Adapter.trigger / History.Adapter.onDomLoad

左からイベントの登録、イベントの強制発火、DOM 構築完了時のコールバック関数登録メソッドですが、それぞれ、一緒に利用するフレームワークに合わせてその処理を移譲するように出来ているようです。

history.adapter.${指定フレームワーク}.js という .js ファイルもロードする必要があるのですが、ここで例えば history.adapter.jquery.js をロードしていれば、

  • History.Adapter.bind: は jQuery の .bind()
  • History.Adapter.trigger: は jQuery の .trigger()
  • History.Adapter.onDomLoad: は jQuery の $(function(){…})

と、対応するようです。

便利なところ

history.pushState() 未対応ブラウザに対する同等機能+便利機能の提供

history.pushState() に見対応なブラウザに対しても、同じ使用感でこの機能が使えるのは快適でした。

History.pushState() 第二引数の title が title 要素に反映される点は、遷移先の title が判っていれば a 要素の title 属性に仕込んでおいたり、data-* 属性に仕込んでおいたり JavaScript のソースに書いておいたりしたのを使えば、自分で Ajax のレスポンスから値を取得して title 要素のテキストを差し替えるといった手間が省けて便利だなぁと感じました。

popstate イベントの発火も伴う点についても、click イベントのデフォルト挙動をキャンセルして popstate イベントの強制発火というのを自分で行うことが多いのではないかと考えると、これもまた便利なものだと感じます。

History.getState() による現在の履歴エントリ情報の取得

一応、現在の履歴エントリの情報を得る手段としては、HTML5 History API における history.state プロパティの参照によっても行えます。

しかし、history.pushState() に対応しているけれど history.state には対応していない。といったブラウザ(Safari5)も存在しており、History API に全く未対応なブラウザも含めてこの辺りの違いを吸収し、どのブラウザでも同じ情報を取得できるこの機能はとても便利です。

また、history.state プロパティに格納されている値は、history.pushState() の第一引数に渡した値のみであり、History.getState() によって得られるオブジェクトには History.pushState() に渡した第三引数までの全ての値が得られます。

ただ、この点については特別にすごい!といった感想ではなく、基本的には第一引数の state 情報を基にした画面更新のパターンを組んでおいた方が良いと感じます。
何かしら手詰まりに陥った状況では情報が少しでも多いのは助かりますし、もしかしたらこれが役に立つ場面があるかもしれません、くらいの認識です。

参考情報

Manipulating the browser history – MDN Docs
https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

history.pushState、history.replaceState – 素人がプログラミングを勉強するブログ
http://d.hatena.ne.jp/javascripter/20100404/1270411268

macbook へ Flex SDK と rascut を入れる際に大変参考になった URL

詳しい導入手順はググれば色々出てくるので、
自分が真似てみて実際に遭遇したエラーなんかのメモです。

  1. Flex SDK は適当にググッて好きな場所へ配置
    (~/Library/Flex/flexsdk4.5.1/ にしときました。)
  2. mxmlc が早速コンソールで文字化けを起こしたところ、こんな記事があって助かりました。

Mac OS Xで、Flex SDK 4.5を使ってゲームを作るためにやったこと – teikouの日記
http://d.hatena.ne.jp/teikou/20110702

  1. mxmlc Hello.as と、Hello World し終えたので rascut も入れようとするけどエラー。
    まさにこちらの記事の通りだったので、これもまた大助かりです。
    先に mongrel を –pre オプションで入れると良い模様。

rascut + Ruby 1.9.2 – ikeasの日記
http://d.hatena.ne.jp/ikeas/20110416/1302949899

  1. rascut を起動するともう一度エラー。これも上記の記事の後半の手順で対応できました。
  2. これでコンソールから rascut Hello.as のコマンドで Hello.as の変更を監視。
    変更があったら自動でコンパイルをしてくれるようになりました。

第30回 Sugamo.css へ行ってきた

Sugamo.css という、Sig.さんの主催されている Web フロントエンドな集まりへ行ってきたのでメモ。発表の辺りとかを中心に、自分も適当に作業しながらだったりしたので聞き取っていたところだけになっています。順序も少し、うろおぼえかもしれません。

第30回 Sugamo.css : ATND
http://atnd.org/events/17263

発表メモ

@yomotsu さん

Adobe Illustrator からの SVG 書き出し

  • 座標とかの情報は小数点第何位までというのがコントロールできる
  • Web 用に保存を使うとレイヤーとかが消えてしまう
  • 別名に保存を使えば g 要素でレイヤーが残る。 id はレイヤーの名前になる。
  • 小数点を丸めればファイルサイズの削減ができる
  • DW で SVG 要素を記述するための補完機能とかライブビューとか載ってる (CS 5.5)
  • (全体的に結構最近めな Adobe CS の機能かも)

@ykhs (自分)

慣性ドラッグの jQuery プラグイン紹介

  • これ。 SAMPLE – jquery.ui.phantomDrag.js http://ykhs.github.com/jquery.ui.phantomDrag/sample.html

  • 自己紹介のつもりで、さっと出せるもので話そうとしたつもりだったけど、やっぱり難しい。慣れとか練習とかは要る。

  • 何をどこまで話すか。簡単にデモを見せただけだったのだけど、ソースとか見せながら突っ込んだ話もしてフィードバックを頂ける流れを作れたら良かったかもしれない。

@neotag さん

Sass について。RubyGems の compass とか

  • (Sass と聞いて黙々試してみるモードになってたので、たぶんこれ以降のいくつかの発表が抜けてしまっているかと思います。)
  • “sass –watch .” とすれば input.scss:output.css の記述を省略できて楽。
  • compass 便利。config.rb を用意して –style :expanded の設定とかを統一できる。チームでの利用に必須っぽい。
  • CSS スプライト作成支援機能もある模様。
  • Web に上がっている公式ドキュメントの内容が古い。自分で調べて使う感じ。

@takazudo さん

GAE で作ってる物紹介

  • GAE で作り中のものを少し見せていただけた。
  • 僕も GAE とか heroku とかそれ系なのいじってみたいな~欲が上がりました。

@yomotsu さん(2)

最初のは前振りで、本番。SVG で地図

  • SVG Animation でかっこよく動く地図。
  • viewBox の話。SVG 画像を表示する原点と横幅・高さを決められる?

@taku_eof さん

WeakMap の話

  • オブジェクトをキーとした値を定義できる
  • そのキーとなるオブジェクトがガベージコレクトされてしまう可能性があるため for in とかでキーの列挙はできない

まとめ

  • SVGで地図を扱うというのはやってみたいし、理にかなってる。Gif画像をイメージマップ切って扱うとかよりスマートだと思う。Raphaël とか使ってレガシーブラウザも考慮してねっていうのは必要だろうけど。
  • Sassはメンバー間のコーディングスタイルの違いを吸収、資産の積み重ねをしていくのにとても良いな~とは感じていて、さらに今回伺った compass でプロジェクト設定みたいなことも出来るようになっていてますます良いな~と思った。

慣性ドラッグプラグインを使ったスライダーの作例

このプラグインは書き直されていて、以下が新しい内容となります。

慣性ドラッグの jQuery UI プラグインを書き直した
http://text.ykhs.org/2011/09/26/jquery-ui-phantomDrag-rewrite.html

前に、慣性の付いたマウスドラッグの挙動作成を助けるようなプラグインを作ったのですが、これを使ったごく簡単な作例で、もう少し、実際にありそうな作り物に近いものを載せたかったので書いてみました。

サンプルページ

Sample っていうところに並んでいる黒い四角の物体たちをマウスドラッグで動かせます。

SAMPLE – Slider using jquery.ui.phantomDrag.js
http://ykhs.github.com/jquery.ui.phantomDrag/sample_slider.html

主なコード

これがプラグインを読み込んだ上で実際の挙動を実現しているコードです。\ ここでやってることだけなら、jQuery UI Widget なんて使う必要はなかったりもしますが、簡単な例ということで。

けれども、込み入った UI なんかを作っているとプラグイン内部のメソッドに外からこのタイミングでアクセスしたい。というのが出てきたり、そのためのメソッドを追加するための継承をしたくなってきたりとかするのではないかと。ということで、そういうことのし易い形で最初から作っとこう、という風になっています。