script.aculo.usを読み解く

第6回 effects.js(後編)基礎エフェクトの組み合わせからなる15種類の複合エフェクト

この記事を読むのに必要な時間:およそ 23.5 分

Effect.Squish

0739:// Bug in opera makes the TD containing this element expand for a instance after finish 
0740:Effect.Squish = function(element) {
0741:  return new Effect.Scale(element, window.opera ? 1 : 0, { 
0742:    restoreAfterFinish: true,
0743:    beforeSetup: function(effect) {
0744:      effect.element.makeClipping(); 
0745:    },  
0746:    afterFinishInternal: function(effect) {
0747:      effect.element.hide().undoClipping(); 
0748:    }
0749:  });
0750:};
0751:

739~751行目のEffect.Squishは,縮小して消えるエフェクトです。ほとんどEffect.Scaleと変わりません。

741行目で,Effect.Scaleを,倍率0IEではチラツキが起きるので1でかけます。オプションは以下です。

742行目で,エフェクト後に大きさを戻します。

743行目で,初期化前のフックで,要素をmakeClippingでoverflow: 'hidden'にして,クリップされる状態にします。

746行目で,終了後のフックで,要素を隠すとともに,要素をundoClippingしてoverflowを元に戻します。

Effect.Grow

0752:Effect.Grow = function(element) {
0753:  element = $(element);
0754:  var options = Object.extend({
0755:    direction: 'center',
0756:    moveTransition: Effect.Transitions.sinoidal,
0757:    scaleTransition: Effect.Transitions.sinoidal,
0758:    opacityTransition: Effect.Transitions.full
0759:  }, arguments[1] || { });
0760:  var oldStyle = {
0761:    top: element.style.top,
0762:    left: element.style.left,
0763:    height: element.style.height,
0764:    width: element.style.width,
0765:    opacity: element.getInlineOpacity() };
0766:
0767:  var dims = element.getDimensions();    
0768:  var initialMoveX, initialMoveY;
0769:  var moveX, moveY;
0770:  
0771:  switch (options.direction) {
0772:    case 'top-left':
0773:      initialMoveX = initialMoveY = moveX = moveY = 0; 
0774:      break;
0775:    case 'top-right':
0776:      initialMoveX = dims.width;
0777:      initialMoveY = moveY = 0;
0778:      moveX = -dims.width;
0779:      break;
0780:    case 'bottom-left':
0781:      initialMoveX = moveX = 0;
0782:      initialMoveY = dims.height;
0783:      moveY = -dims.height;
0784:      break;
0785:    case 'bottom-right':
0786:      initialMoveX = dims.width;
0787:      initialMoveY = dims.height;
0788:      moveX = -dims.width;
0789:      moveY = -dims.height;
0790:      break;
0791:    case 'center':
0792:      initialMoveX = dims.width / 2;
0793:      initialMoveY = dims.height / 2;
0794:      moveX = -dims.width / 2;
0795:      moveY = -dims.height / 2;
0796:      break;
0797:  }
0798:  
0799:  return new Effect.Move(element, {
0800:    x: initialMoveX,
0801:    y: initialMoveY,
0802:    duration: 0.01, 
0803:    beforeSetup: function(effect) {
0804:      effect.element.hide().makeClipping().makePositioned();
0805:    },
0806:    afterFinishInternal: function(effect) {
0807:      new Effect.Parallel(
0808:        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
0809:          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
0810:          new Effect.Scale(effect.element, 100, {
0811:            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
0812:            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
0813:        ], Object.extend({
0814:             beforeSetup: function(effect) {
0815:               effect.effects[0].element.setStyle({height: '0px'}).show(); 
0816:             },
0817:             afterFinishInternal: function(effect) {
0818:               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); 
0819:             }
0820:           }, options)
0821:      )
0822:    }
0823:  });
0824:};
0825:

752~825行目のEffect.Growは,飛び出すように拡大して現れるエフェクトです。飛び出しの出発点を選べるようになっています。出発点までの移動にEffect.Moveを0.01秒だけ使っています。その後の飛び出すエフェクトは,Effect.OpacityとEffect.MoveとEffect.ScaleをEffect.Parallelで並列に動かすことからできています。Effect.MoveとEffect.Scaleを同時に使うのは、後述するように、出発点を動かさずに拡大しているように見せるためです。

754~759行目で,デフォルト設定を作ります。

755行目で,飛び出しの出発点は'center'(中央)です。

756行目で,飛び出すときの角の位置の変化は,sinoidalです。

757行目で,飛び出すときの大きさの変化は,sinoidalです。角の動きと広がりが同期するので,出発点を中心に広がるように見えます。

758行目で,飛び出すときの透明度の変化は,fullで,常に1(不透明)です。デフォルトでは、変化がないので、後述のEffect.Opacityの意味がありません。

760~765行目で,要素の位置と大きさと透明度を保存します。エフェクト後に元に戻すためです。

767行目で,要素のサイズを取得します。

768行目で,initialMoveXとinitialMoveYは出発点の相対位置です。

769行目で,moveXとmoveYは,角(かど)の位置の移動量です。initialMoveXとinitialMoveYの符号を逆にしたものに等しいです。

771~797行目で,飛び出しの出発点のオプションについて場合分けします。

'top-left'移動する必要がありません。Effect.Scaleだけで充分です。
'top-right'右上の出発点が動いていないように見せるため,左に移動しながら大きさを変えます。
'bottom-left'同様に,上に移動しながら大きさを変えます。
'bottom-right'同様に,左上に移動しながら大きさを変えます。
'center'同様に,左上に移動しながら大きさを変えます。これはEffect.ScaleでscaleFromCenterとしても同じでしょう。

799行目で,Effect.Moveで,出発点まで0.01秒で移動します。これはEffect.Eventを使ってもよいでしょう。

803行目で,初期化前のフックで,要素を隠すとともに,makeClippingでoverflowを'hidden'にし,クリップされるようにし,makePositionedでpositionを'relative'にして,移動に備えます。

806行目で,終了後のフックで,飛び出すエフェクトをかけます。Effect.Parallelで,3つのエフェクト(Opacity,Move,Scale)を並列にかけます。

808行目で,Effect.Opacityで,0.0(透明)から1.0(不透明)に向けて変化させますが,デフォルトだとtransitionがfullになるので,ずっと1.0(不透明)です。デフォルトだとこのエフェクトの意味はありません。

809行目で,Effect.Moveで,位置を大きさの変化と同期して動かすことで,出発点を動かさずに広がっているように見せます。

810行目で,Effect.Scaleで,目標倍率は100%(等倍)⁠大きさの基準はgetDimensionsで取得したもの,初期倍率は0IEではチラツキが起きるので1)⁠終了後に元に戻します。

814行目で,初期化前のフックで,要素の高さを0pxにして,表示します。

817行目で,終了後のフックで,要素をundoClippingしてoverflowを元に戻し,undoPositionedでpositionを元に戻し,位置と大きさと透明度を元に戻します。

著者プロフィール

源馬照明(げんまてるあき)

名古屋大学大学院多元数理科学研究科1年。学部生のときにSchemeの素晴らしさを知ったのをきっかけに,関数型言語の世界へ。JavaScriptに,ブラウザからすぐに試せる関数型言語としての魅力と将来性を感じている。

ブログ:Gemmaの日記