08 | 2017/09 |  10

  1. 無料サーバー

User forum-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

CSSやJavascript自習の苦闘史を綴っていきたい。恐縮ですがJavascriptを有効にしてご覧ください。
2005年12月から社会問題も掲載!

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

 

jquery.js におけるアニメーションコードの解読 ( 3 )

このエントリイでは、jquery アニメーションで活用される基本的な次の 5 つの関数やメソッドを解読します。

genFx、show、hide、toggle、fadeTo

genFx( type, num )

引数:第 1 引数の type には show 、hide 又は toggle を代入し、第 2 引数 num には 1~3 を代入して利用します。

返値:オブジェクト

機能:配列 fxAttrs からプロパティ名を CSS style 属性名、プロパティ値を type とするオブジェクトを生成します。

この関数は、要素を 「非表示 → 表示へ」、「表示 → 非表示へ」、「表示/非表示の循環」とアニメートさせるために、animate メソッドの第 1 引数である prop オブジェクトを作成するものです。CSS スタイル値を toggle、show、hide とするので最初は違和感があります。しかし、アニメーションの全容を理解すれば、この関数の必要性や重要性が理解できます。

■genFx( type, num ) 関数コード解読
3765:var elemdisplay = {}, // トップレベルで 3 つの変数を定義する。
3766: timerId,
3767: fxAttrs = [
3768:  // height animations
3769:  [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
3770:  // width animations
3771:  [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
3772:  // opacity animations
3773:  [ "opacity" ]
3774: ];
3775:
3776:function genFx( type, num ){
3777: var obj = {};
    // each 適用対象は num==1 ならば ["height",・・・,"paddingBottom"]、
    // num==3 ならば ["height",・・・,"paddingBottom","width",・・・,"opacity"] となる。
3778: jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
3779:  obj[ this ] = type; // each 適用対象ごとに type 値を代入し、
3780: });
3781: return obj; // obj={ height:type, marginTop:type, ・・・} となる。
    // つまり、返値は CSS style 属性名をプロパティ名とし、
    // type をプロパティ値とする複数のプロパティからなるオブジェクトとなる。
3782:}

▲ToTop

jQuery().show(speed,callback)

引数:アニメの継続時間、アニメ終了後に起動させるcallback 関数

返値:jQuery インスタンス

機能:言うまでもなく jQuery インスタンスに登録されている要素を表示させるメソッドです。

要素の display プロパティ値は、block だけではなく inline やその他の指定もあります( inline-block、table、inline-table 等々 )。ですから、「このメソッドは引数を与えなければ、単に display="block" とするだけの単純な関数だろう」との推測は、見事に裏切られてしまいます。

コードは2つの部分から成り、引数がある場合には animate メソッドが起動されますが、その解説は animate メソッドの項に譲り、ここでは引数がない場合の show メソッドの進行を跡付けます。

show メソッドの要点

第一は、hide メソッドも同様ですが、当該メソッドが同一インスタンスに対して複数回呼び出された場合の対応についてです。2 度目以降の呼び出しに対して省力化の仕組みが組み込まれており、そのことやその意義を理解する必要があります。

第二は、display プロパティについて、その算出( IE の場合には「カレント」と呼ぶことが多い)スタイル値と style オブジェクトのプロパティ値の区別を理解しなければならないということです。明示的なスタイル設定と暗黙裏に設定されるスタイル値は別物であることを踏まえなければなりません。

▲ToTop

以上のことを踏まえてコード進行を見てみます。

或る jQuery インスタンスに初めて show メソッドを適用する場合
  • あるインスタンスに対して初めて show メソッドを適用すると、jQuery.data メソッドの定義から、この時点では olddisplay 名で関連づけられた情報は存在しないので、style.display に空文字が代入されます(#3790-3792)。つまり this.style.display プロパティ値を初期化します。
  • 次に、jQuery.css メソッドにより当該要素の算出(カレント)display スタイル値を検証し、それが none だったら(#3794)トップレベル変数である elemdisplay オブジェクトの、当該要素のタグネーム名のプロパティ値の有無を調べます。この時、同一名称のタグに対して過去に show メソッドが呼び出されていなければ、このプロパティは存在していませんから、3800 行以下が履行されます。
    • 3800 行から3808 行では、show メソッドが対象としているタグ要素と同じ名称のタグを当該サイト内の body 部に追加し、そのカレントスタイル値を取得し、その値が none 以外ならばそのプロパティ値を、他方 none ならば "block" を、elemdisplay[ tagName ] に代入します。(#3808)
    • こうして elemdisplay[ tagName ]プロパティ値を利用するか、あるいはそれに none 以外のプロパティ値を代入した後に、インスタンスの各要素に olddisplay 名で display 値を関連づけます(#3811)。
    • ここに変数 display 値は、elemdisplay 値が存在した場合、すなわち同じタグ名称の他の要素に対して show メソッドが適用済みの場合(当該インスタンスタンス内の他の同一名称のタグに適用済みの場合を含む。対象としたインスタンス内のタグ名称が全て同じ場合には、2巡目以降の場合がこれに該当する)には、elemdisplay 値になります。
    • 他方、elemdisplay が存在しなかった場合には、当該サイト内において今対象としているタグ要素に暗黙裏に設定されている display スタイル値が、none ならば block に、none 以外であれば当該値( block、inline等々 )となります。
  • こうして当該要素にそれに相応しい display 値が与えられ、ブラウザがそれにより当該要素を描画し、ディスプレイ画面に表示させます。

▲ToTop

同じ要素に対して二度以上の show メソッドを適用した場合

次に、同じ要素に対して二度以上の show メソッドを適用した場合を跡付けます。

この場合には、既に一度目の show メソッド適用によって、変数 elemdisplay オブジェクトの当該要素と同一のタグネームプロパティ値が none 以外となっており、かつ当該要素には olddisplay 名で none 以外の display 属性値がテキスト文字列で関連づけられています。

この結果、3792 行により当該要素の style オブジェクトの display 値が none 以外の値に設定され、更に constant reflow を避けるために設けられた 3817 行により、再度 style.display 値が none 以外の block 等となります。

なお、constant reflow を直訳すれば「定期的な再流」ですが、これでは何のことか皆目分かりません。ネット検索してみましたが未解明です。

show インスタンスメソッドが複雑なコードになっている理由

ところで、当初は show メソッドは単純に if (this[i].style.display=="none") this[i].style.display="block" とするだけで用が足りると思っていましたから、どうしてこのように複雑なコードになっているのか、その理由をここで考えてみたいと思います。

まず、elemdisplay オブジェクトの存在意義です。どうしてトップレベルの変数に、対象としている要素と同一のタグネームプロパティを設け、その値を none 以外とするのでしょうか。あたかも同一タグ名称の要素の display プロパティ値を、1 つに統一する必要があるかのようです。

例えば、ある p タグの n 番目の要素( p(n)と名付ける )を show メソッドで表示させたとします。すると elemdisplay.p = "block" となり、p タグの n 番目以外の要素( p(m)と呼ぶ )に show メソッドを適用する場合には、#3799~3809 がスルーされ、#3811 で olddisplay 名で文字列 block が p(m) に関連づけられ、最後に #3818 によって p(m) の display 値が block となり、ブラウザ上に p(m) 要素が表示されます。

append 行為を同一名称の要素に対して 2 度以上引き起こさせない効率化が目的なのかもしれません。但し、それ以外の目的があるかどうか、また、あるとすれば何かについては解明できていません。

次に、同一タグ名の要素を わざわざ append するのは何故でしょうか。

それは次のような理由によると考えられます。

body に対象要素と同一タグ名称の要素を追加し、その算出(カレント) display 属性を調べれば、そのサイトにおいて、当該タグがどのような display 値をとっているのか把握することが出来ます。この方法によって、当該タグがサイト内で有する算出(カレント)display 値を取得することにしたのでしょう。

これに対して、olddisplay 名による要素への none 以外の文字列の関連づけは、分かりやすいものです。jQuery.data メソッドを利用するのは、一度当該要素の display 属性値を none 以外に登録した要素に対して、二度目以降はこの登録済み文字列を利用して容易に display 値を同じ値に設定するためです。show メソッドにおいても hide メソッドにおいても、jQuery.data メソッドがしっかり活かされています。

■$().show メソッドコード解読
3785: show: function(speed,callback){
3786:  if ( speed ) { // 引数 speed が定義されていれば
      // 「genFx("show",3 )を CSS スタイル値、speed をアニメ所要時間とし、
      // callback 関数をアニメ終了後に起動する animateメソッドを、
      // jQuery インスタンスから呼び出して実行し、その返値を返す。
3787:   return this.animate( genFx("show", 3), speed, callback);
3788:  } else { // 引数 speed が未定義か null 値の時、インスタンスの個々の要素に対して
3789:   for ( var i = 0, l = this.length; i < l; i++ ){
       // olddisplay なる名称で各要素ノードに関連付けられている値を取り出す。
       // 関連づけられた値がない場合には old = false となる。
       // 当該要素ノードに対する初めての show() 適用時には old は false と
       // なるが、二度目以降の呼び出し時には 3811 行で関連づけが定義済みなので
       // old = "block" となる。
3790:    var old = jQuery.data(this[i], "olddisplay");
3791:    // old があれば各要素ノードの display スタイル値に old を、
       // old が false ならば null を代入する。
3792:    this[i].style.display = old || "";
3793:    // 各要素ノードの display スタイル値が "none" ならば
3794:    if ( jQuery.css(this[i], "display") === "none" ) {
3795:     var tagName = this[i].tagName, display; // ローカル変数定義
3796:     // 当該要素ノードに対する初めての show() 適用時には
        // elemdisplay[ tagName ] プロパティは存在していないが、二度目以降の
        // 呼び出し時には 3808 行で定義済みなので存在していることになる。
        // elemdisplay オブジェクトに tagName プロパティがあれば、
3797:     if ( elemdisplay[ tagName ] ) {
3798:      display = elemdisplay[ tagName ]; // display 値をその値とする。
3799:     } else { // elemdisplay オブジェクトに tagName プロパティがなければ
         // tagName と同じ名称の要素ノードを作成し、body 追加後に参照を取得する。
3800:      var elem = jQuery("<" + tagName + " />").appendTo("body");
3801:      // 追加したノードの display 属性を取得する。
3802:      display = elem.css("display");
3803:      if ( display === "none" ) // もしもその値が "none" ならば
3804:       display = "block"; // "block" に変更する。
3805:      // body に追加したノードを削除し、
3806:      elem.remove();
3807:      // elemdisplay の tagName プロパティ値を display つまり "block" とする。
3808:      elemdisplay[ tagName ] = display;
3809:     }
3810:     // 各要素ノードに olddisplay 名の display 値 つまり "block" を関連づける。
3811:     jQuery.data(this[i], "olddisplay", display);
3812:    }
3813:   }
3814:
3815:   // Set the display of the elements in a second loop
3816:   // to avoid the constant reflow
3817:   for ( var i = 0, l = this.length; i < l; i++ ){
       // 各要素ノードの display スタイル属性を olddisplay 名で関連づけら
       // れている値("block")、又は null に設定する。
3818:    this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
3819:   }
3820:
3821:   return this; // インスタンスを返す。
3822:  }
3823: },

▲ToTop

jQuery().hide(speed,callback)メソッドの解読

引数:継続時間、callback関数

返値:jQueryインスタンス

機能:言うまでもなく jQuery インスタンスに属する要素を隠蔽させるメソッドです。

このメソッドにおいても引数が与えられた場合には、animate メソッドが利用されますがここでは触れません。引数がない場合のみ解読します。

ある要素に初めて hide メソッドを適用した場合

インスタンスの個々の要素に対して、最初に hide メソッドが適用された場合において、既に当該要素に show メソッドが適用されていれば、当該要素に olddisplay 名で関連づけられた情報は block や inline となっており、一度も show メソッドが適用されていなければ、当該要素に olddisplay 名で関連づけられた情報は存在しません。

つまり、#3830 の変数 old には、block、inline などのスタイル値か、又は undefined が代入されます。そして old が undefined 値の場合、!old==true となり、勿論 old!=="none" が成立します。

こうして事前に show メソッドが適用されていない要素に対して、初めて hide メソッドを適用した時には、#3832 が実行され、data メソッドと css メソッドにより、当該要素の style.display 値、または算出(カレント)display 値が、olddisplay 名で当該要素に関連づけられます。
(関連づけられる値は block、inlineblock、inline 等となりますが、if 条件から none だけはあり得ません。olddisplay 値は block や inline などの表示用の値となり、none となることは決してありません。)

show メソッドの後に hide メソッドを適用した場合、あるいは hide メソッドを二度以上適用した場合

他方、show メソッドが適用された後に hide メソッドを適用した場合や、同一要素に対して二度目以降の hide メソッドを適用した場合には、old は未定義ではなくなっていますから !old=false となり、#3831~3832 は実行されないまま、#3837~3838 が実行され当該要素は非表示、あるいは非表示のママとなります。

上の行為の後に再び show メソッドを適用した場合

olddisplay 値は block や inline 等となっているので、3792 行により display 値はそのままとなります。よって #3794-3812 は通過し、3818 行が実行されて当該要素が表示されることになります。

■$().hide メソッドコード解読
3825: hide: function(speed,callback){
3826:  if ( speed ) { // speed があれば animate メソッドを実行する。
3827:   return this.animate( genFx("hide", 3), speed, callback);
3828:  } else { // speed がないか null の時
3829:   for ( var i = 0, l = this.length; i < l; i++ ){
       // 各要素に olddisplay 名で関連づけられているデータを変数 old に代入する
3830:    var old = jQuery.data(this[i], "olddisplay");
3831:    if ( !old && old !== "none" ) // old が false か "none"でない時には
        // 各要素ノードの display スタイル値を
        // olddisplay 名で各要素ノードに関連づける。
3832:     jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
3833:   }
3834:
3835:   // Set the display of the elements in a second loop
3836:   // to avoid the constant reflow
3837:   for ( var i = 0, l = this.length; i < l; i++ ){
3838:    this[i].style.display = "none"; // 非表示を設定する。
3839:   }
3840:
3841:   return this; // インスタンスを返す。
3842:  }
3843: },
3844:

▲ToTop

jQuery().toggle(fn,fn2)

引数:fn,fn2

返値:jQueryインスタンス

機能:jQuery インスタンスに属する要素を表示/隠蔽させる循環メソッドです。

toggle メソッドはイベント処理にも登場します。それが最初の分岐(#3851)の2つの引数が共に関数の場合です。この場合には 3852 行が適用されてイベントの toggle 処理が行われます。

fn、fn2 が共に存在しない場合、あるいはいずれか一方以上が関数でない場合が、アニメ-ション処理で利用する toggle メソッドです。

アニメで利用する toggle メソッドは 2 つのケースに分かれます。

第 1 のケースは、fn、fn2が共に存在しない場合、あるいは第1引数が真偽値の場合です。このときにはインスタンスに登録されている各要素毎に次のことを行います。

  1. 最初の引数が真偽値で true ならばその値を state に代入します。
  2. bool がない場合(つまり引数が全くない場合)や、最初の引数が false の場合には、対象要素のhidden 属性の有無を調べ、あれば true、なければ false を state に代入します。つまり引数を全く指定しない場合や、fn == false と指定した場合には、当該要素の hidden 属性の有無によって、state に代入される値が決まります。hidden 属性があれば true、なければ false となります。(#3855)
  3. 次に、state が true ならば、jQuery(this).show() メソッドを実行し、false ならば、jQuery(this).hide() メソッドを実行します。(#3856)

第 2 のケースは fn、fn2 のいずれか一方以上が関数でない場合で、かつ最初の引数が真偽値でない場合です。このときには、"toggle" をアニメ用オブジェクトのプロパティ値とし、fn と fn2 を順に speed、easing として、インスタンスから animate メソッドを起動します。(#3858)この animate メソッドにおいて第 1 引数であるオブジェクトのプロパティ値を toggle とする場合の挙動は別途詳述します。

■ toggle インスタンスメソッド
3845: // Save the old toggle function
3846: _toggle: jQuery.fn.toggle,
3847:
3848: toggle: function( fn, fn2 ){
3849:  var bool = typeof fn === "boolean"; // fn が真偽値かどうかを bool に代入
3850:  // (1)fn も fn2 も関数ならば_toggle メソッドを実行する。
     //(このケースはイベント処理時に登場する)
3851:  return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
3852:   this._toggle.apply( this, arguments ) :
     // (2)引数がない場合、あるいはfn か fn2 のいずれか1つ以上が関数でない場合には、
      // (2-1)引数がないか、または fn が bool(真偽値)ならば
3853:   fn == null || bool ?
3854:    this.each(function(){ //各インスタンス毎に
        // bool が true ならば fn を、bool がない場合や false ならば当該要素の
        // hidden 属性有無(true or false)を変数 state に代入する。
3855:     var state = bool ? fn : jQuery(this).is(":hidden");
        // state が true ならば show メソッドを、
        // state が false ならば hide メソッドをそれぞれ起動する。
3856:     jQuery(this)[ state ? "show" : "hide" ]();
3857:    }) :
      // (2-2)fn が null でもなく真偽値でもない場合animateメソッドを実行する。
3858:    this.animate(genFx("toggle", 3), fn, fn2);
3859: },

▲ToTop

jQuery().fadeTo()

引数:speed、to、callback

返値:jQueryインスタンス

機能:不透明度を to、speed を duration、callback をアニメ終了後に実行される関数とする、animate メソッドを起動します。

■ fadeTo メソッド
3861: fadeTo: function(speed,to,callback){
3862:  return this.animate({opacity: to}, speed, callback);
3863: },

▲ToTop

 

■ コメントの投稿 ■

管理者にだけ表示を許可する

●トラックバック●

■トラックバックURLはこちら■
http://hkom.blog1.fc2.com/tb.php/720-5d0836e1

●参照元一覧●

<provided Fc2>
<provided i2i>

▲ToTop

 90%近いシェアを握っているインターネットエクスプローラの描画エンジンを利用したタブbrowser。沢山のタブbrowserがあるが、多機能、カスタマイズフリー、スクリプト利用等で一日の長がある。Gekkoエンジンへの対応も行われ、IEからの自立独立の方向に向かっている。2005年7月にはIE7が登場する見通しの中で、今後の発展が望まれる。

 多様なCSS作成支援機能を備えた、タグ入力式 HTML&CSS作成支援エディタ。スキンデザインもすっきりしている。テキストエディター上で作成するよりも確実で安全にタグ打ちが出来る。
文字コードを選べないのが欠点。

 StyleNote同様のタグ入力式 HTML&CSS 作成支援エディタ。長年使用してきたが現在StyleNoteに乗り換えつつある。

 クリップボード履歴情報を活用する為のソフト。画像まで履歴を取ってくれるのが嬉しい。このソフトを使わない日は絶対ない程に重宝し、愛用している。

 起動中のウィンドウの「コピーできない」説明文などの文字列を取得し、コピー可能な文字データにするツール。何かと便利。

 ストリーミングデータを保存することが出来るソフト。動画利用には不可欠なソフトだ。

 無料ながらレイヤー機能を有し、スクリプトによる拡張も可能な、sleipnir作者が提供している優れもの画像編集ソフト。

 画面キャプチャソフトと言えばこれに勝るものなし、ではないだろうか? 様々な取得方法を有しており、ブログ作成にもHomepage作成に不可欠だ。Jtrimと並んでWoodyBellsの作品。

 複数ファイルの同時編集は出来ないが、透過pngも作れる画像編集ソフト。
(以下当該サイトから抜粋)初心者にも簡単に操作が出来るフォトレタッチソフトです。多くの加工機能で画像に様々な効果を与えることができます。非常に軽快に動作するため、ストレスなく操作できます。

 Animation Gifファイルを作れる無料ソフト。

 キャプチャソフト。画面内にサイト全体が表示しきれない場合でも、これを使えば全体をキャプチャすることが出来る。

 画像処理。画像のフォーマット変換のみならず、色数やサイズ、圧縮率の変更まで一括処理できてしまう『BatchGOO!』は、大量の画像をまとめて処理したいときに大変便利なソフト。BMP, TIFF, JPEG, PCX, PNG の相互変換をはじめ、色数・サイズ・解像度の統一、JPEG圧縮率の調節など、ホームページ用の画像や携帯電話用の壁紙を揃えるのに抜群の相性を見せる。(Vectorの当該ソフト紹介頁より抜粋引用)

 名前から直ぐに想像が付くように画像のサイズを測るためのソフトだ。Homepage作成には欠かせない。2カラム、3カラムのレイアウトを行う場合に大変重宝する。

 ランチャーソフトは沢山あるが、中でもこれが一押しだ。2年以上使ってきたがその操作性には毎日満足している。これを使い始めてからデスクトップには一切のアイコンを表示することをやめてしまった。

 AdobeReader7によって、起動時間が長すぎるという長年のユーザーの不満はある程度解消した。そのためこの高速化ソフトは存在価値が低下してしまったかもしれない。AdobeReader6迄はこのソフトによる起動高速化で恩恵を受けてきた。

 IE専用が難点だが、様々なサイト内でIDやパスワードを入力するのに重宝するソフト。コンテキストメニューから簡単に起動できるのがGood! sleipnir等のIEの描画エンジンを利用しているブラウザでも使える。

 利用しているパソコンの諸元値を取得するには、このソフトがベストだ。インストール済みソフトの一覧が取得できるのも嬉しい。

 WMPは機能が豊富なだけ重い。RealPlayerも同様だ。そこでMedia Player Classicを使いたい。動作が軽快なだけではなく、対応しているファイル形式もすこぶる多く、これひとつで、wmvもrmも表示できてしまうのだから凄い! 数多あるMedia Playerの王様と言えるだろう。

 自宅でPCを起動しているときには必ず起動しているメディアプレーヤー。何かと過剰なWinampよりも、起動も速くスキンはシンプルだ。

 DivX, Xvid, Mov, Vob, Mpeg, Mpeg4, avi, wmv, dv, などの動画をDVD-Video形式に変換できるフリーソフト。クリックするとDVD関連ソフト紹介サイト=「DVDなToolたち」なるHomepageが開きます。

----------
200907201110
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。