共通のJavaScript効果ライブラリを書く方法!(1/2)

13122 ワード

JavaScriptのダイナミック効果は、サイズのダイナミックな変更、位置の移動、透明度の変更、色の変更などが基本です.
他のいくつかの比較的眩しい効果は、これらの最も基本的な効果の組み合わせと運用にほかならない.
現在、ネット上には素晴らしいJavascriptライブラリや効果ライブラリがたくさんありますが、車輪を再構築する必要がありますか?
見渡すとYahoo UI、Prototypeベースのscriptaculous、Rico、JQuery、Dojo、まだまだたくさんあります.
これらのライブラリには、優れたダイナミックな効果があります.私たちは直接使うことができます.
しかし、一部の中小規模プロジェクトでは、たまに1、2つの特効を使うだけで、フレームワーク全体を引用する必要はありません.
こいつらは体積が小さくないよ. prototype.js 50 K,scripttaculousのeffects.jsも40-50 k dojoあり、yuiはもっと大きいです.
多くの場合、侵入性のないコンパクトで独立した(300行のコード以内)効果ライブラリが必要です.既存の車輪があっても、
私たちは車輪の使い方を学ぶだけでなく、自分の手で車輪を作る方法も学ばなければならない.
以上の理由から、今日は柔軟で、拡張性が高く、コンパクトで、ブラウザにまたがるダイナミックエフェクトライブラリを書き直します.
考えてみればjsユーザー群の広範性、私のコードの一部はprototypeを参照しています.js、もちろん、私たちは独立しなければならないと言った.
prototypeがなくてもjsの場合も、コードを正常に動作させます.
まず準備をします.次のコードは、位置座標を取るような役割を果たすため、効果ライブラリでは欠かせません.
設定、elementの透明度の取得などの基礎的な作業.
コード:
 
  
/* 
      Prototype.js  http://prototype.conio.net/ 
     prototype.js , , 
     , ,  
*/ 
(function(){    
    if     (!("Prototype" in window)){ 
        Prototype={emptyFunction:function(){}}; 
        Class ={ 
            create: function(){return function(){this.initialize.apply(this, arguments)}} 
        };         
        $ = function(element){ 
            return typeof(element)=="string"?document.getElementById(element):element 
        }; 
        $A= function(arrLike){ 
            for(var i=0,ret=[];i            return ret 
        };     

        Number.prototype.toColorPart =function(){return String("00"+this.toString(16)).slice(-2)};         
        Function.prototype.bind = function() { 
             var __method = this, args = $A(arguments), object = args.shift(); 
            return function(){return __method.apply(object, args.concat($A(arguments)))} 
        } 

        Position={  
             cumulativeOffset: function(element) { 
                var valueT = 0, valueL = 0; 
                do { 
                  valueT += element.offsetTop  || 0; 
                  valueL += element.offsetLeft || 0; 
                  element = element.offsetParent; 
                } while (element); 
                return [valueL, valueT]; 
            } 
        }         
    } 
})() 


/* 
    1. /   , 
    2. element,  element  (0    3.  element value  element value  value  0-1 
*/ 
function Opacity(element,value){ 
// by Go_Rush( ) from http://ashun.cnblogs.com/ 
    var ret; 
    if (value===undefined){   //  
        if (!/msie/i.test(navigator.userAgent)) 
            if (ret=element.style.opacity) return parseFloat(ret);           
        try{return element.filters.item('alpha').opacity/100}catch(x){return 1.0} 
    }else{                   //          
        value=Math.min(Math.max(value,0.00001),0.999999)    // ie opacity 1 bug 
        if (/msie/i.test(navigator.userAgent)) return element.style.filter="alpha(opacity="+value*100+")" 
        return element.style.opacity=value         
    } 


では、このEffectエフェクトライブラリをどのように設計しますか.
まず、その入り口は簡潔であるべきだ. 
    1.1つは効果を使用する要素elementです
    2.もう1つは、どのような効果を使用するかoptionsです.
optionsは拡張性が強く、ユーザーが使いやすいはずです.私たちはそれを哈希構造に設計した.
例えばoptions={x:100,y:100}はelementを座標100100に移動することを示す
options={w:200,h:200}はelementのサイズをwidth=200に変更することを示し,height=200
彼らは重ねることができて、例えばoptions={h:20,y:20}これはelementをtop=20の位置に移動することを表して、しかも移動の過程の中で彼の大きさをheight=20に変えて、同時に、元のleft座標と幅はすべて変化しないで、これはQQのスライド効果をしているのではありませんか?
効果を制御するいくつかの重要な要素duration(効果全体の時間)、delay(数秒遅れて効果が始まる)、fps(周波数が速くて遅い)はoptionsを通じて伝わります
 
  
 Effect          =Class.create(); 
 Effect.Fn     =new Object(); 
 Effect.Init   =new Object(); 
               //  By Go_Rush( ) from http://ashun.cnblogs.com/ 
 Effect.prototype={ 
     initialize: function(element,options) { 
         this.element  = $(element); 
         this.options  = options || {}; 
         this.duration   = (this.options.duration || 2) * 1000;   //  
         this.fps            = this.options.fps || 40;                 //  
         // , :  , 0  
         this.steps        = Math.floor(this.duration/this.fps);    
         this.maxSteps = this.steps;             //  
         this.setting     = new Object();   
         this.timer         = null;         

      if (this.options.delay){    //   
                var _this=this; 
              setTimeout(function(){ 
                        _this.setup(_this); 
                        (_this.options.onStart || Prototype.emptyFunction)(_this); 
                        _this.run(); 
                 }, _this.options.delay*1000); 
         }else{ 
                  this.setup(this); 
                 (this.options.onStart || Prototype.emptyFunction)(this);         
                 this.run();       
         } 
    }, 
    run: function() { 
         if (this.isFinished())  return (this.options.onComplete || Prototype.emptyFunction)(this); 
         if (this.timer)   clearTimeout(this.timer); 
         this.duration -= this.fps; 
         this.steps--;                            
         var pos=1-this.steps/this.maxSteps    ;    //  
         this.loop(this,pos);     
         (this.options.onUpdate || Prototype.emptyFunction)(this,pos);       
         this.timer = setTimeout(this.run.bind(this), this.fps); 
    }, 
    isFinished: function() {  
            return this.steps <= 0; 
    }, 
    setup:function(effect){       //  
            for(var key in Effect.Init){ 
             if (typeof(Effect.Init[key])!="function") continue; 
             try{Effect.Init[key](this)}catch(x){} 
         } 
     }, 
    loop:function(effect,pos){           //  
         for(var key in Effect.Fn){ 
             if (typeof(Effect.Fn[key])!="function") continue; 
             try{Effect.Fn[key](effect,pos)}catch(x){} 
         } 
    } 
 } 

ダイナミックエフェクトが変化すると、例えばフェードアウトすると、elementを徐々に薄くして小さくし、消えてしまいます.
効果ライブラリを使用する場合はelementのみを使用する.style.display=「none」でできました.
効果ライブラリを使用すると、element.styleの透明度opacity,寸法width,height,さらに位置left,topが変化した.
elementのサイズが0またはopactiyが0に変更されるまでdisplay=「none」は消えません
では、次に彼を現れさせたとき、どうやって元の情報を復元しますか.例えばwidth.height,opacityなど.
上のコードではeffectを使います.settingは、効果が発生する前のすべてのelement情報を保存する.
以上の3つのカスタム関数onStart,onUpdate,onCompleteはoptionsを介して渡された呼び出し者カスタム関数であることに注意してください.
それぞれ、効果が発生する前、効果が発生した時、効果が発生した後に実行します.入力されたパラメータはeffectのすべてのオブジェクトを参照できます.
ここを見て、細心の注意を払った役人は、この効果庫が実際には何の効果もしていないことに気づいたかもしれません.彼はただ空っぽの棚を作っただけです.
Effect.Initはsetupメソッド呼び出し用の空のインタフェースを残してくれたEffect.Fnもloopメソッド呼び出しのための空のインタフェースである.
次に私たちがしなければならないのはEffectを拡張することです.InitとEffect.Fnは効果ライブラリを充実させる.
まずみんなが一番よく知っているフェードアウトを一つください.
Effect.Initのすべてのメンバー関数はeffectになります.setupが実行され、この実行動作は効果が始まる前に行われるので、ここでは
初期化の動作に適しています.例えばeffectに初期情報を保存する.settingでは後で使用できます.
Effect.Fnのすべてのメンバー関数はeffectされます.loop実行、この実行動作は効果実行中なので、ここでは
計算、効果増分の変更など、コアエフェクトコードを配置します. 
 
  
 if (effect.options.opacity===undefined) return; 
 effect.setting.opacity=Opacity(effect.element);  


Effect.Fn.opacity=function(effect,pos){ 
 if (effect.options.opacity===undefined) return; 
 Opacity(effect.element,effect.setting.opacity+(effect.options.opacity-effect.setting.opacity)*pos);  


デバッグ可能なコード(空の効果ライブラリとフェードアウトプラグイン)を貼り付けます:(html実行、テストにコピーできます)
この関数のコードはPrototypeから来ています.js http://prototype.conio.net/ページがprototypeを参照している場合.jsは、次の関数を削除することができます.もちろん、削除しなくても大丈夫です.簡単な互換性判断*/(function(){if(!(「Prototype」in window){Prototype={emptyFunction:function(){}}をしたからです.Class ={ create: function(){return function(){this.initialize.apply(this, arguments)}} }; $ = function(element){ return typeof(element)=="string"?document.getElementById(element):element }; $A= function(arrLike){ for(var i=0,ret=[];i<arrLike.length;i++) ret[i]=arrLike[i]; return ret }; Number.prototype.toColorPart =function(){return String("00"+this.toString(16)).slice(-2)}; Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function(){return __method.apply(object, args.concat($A(arguments)))} } Position={ cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return [valueL, valueT]; } } } })()/**//* 1.透明度の読み取り/設定、2.パラメータelementが1つしか伝わっていない場合は、elementの透明度(0<value<1)3を返します.2つのパラメータelementとvalueが渡された場合、elementの透明度をvalue value範囲0-1*/function Oppacity(element,value){var ret;if(value==undefined){///if(!/msie/i.test(navigator.userAgent))if(ret=element.style.opacity)returnparseFloat(ret);try{returnelement.filters.item('alpha').opatm('alpha').opopopacity)acity/100 mcatch(x){return 1.0}}else{//value=Math.min(Math.max(value,0.00001),0.999999)/この修復ie以外のブラウザopacityでは1に設定できないバグif(/msie/i.test(navigator.userAgent))return element.style.filter="alpha(opacity="+value*100+")"return element.style.opacity=value}Effect=Class.create(); Effect.Fn =new Object(); Effect.Init =new Object(); Effect.prototype={ initialize: function(element,options) { this.element = $(element); this.options = options || {}; this.duration = (this.options.duration || 2) * 1000;//効果実行時間this.fps = this.options.fps || 40;//頻度this.steps = Math.floor(this.duration/this.fps);//現在のステップ長、注意:この変数は減少し、0の場合、効果全体が終了することを意味します.maxSteps = this.steps;//効果全体のステップ長this.setting = new Object(); this.timer = null; if(this.options.delay){//遅延処理var_this=this;settimout(function(){_this.setup(_this);(_this.options.onStart||Prototype.emptyFunction)(_this);_this.run()},this.options.delay*1000); }else{ this.setup(this); (this.options.onStart || Prototype.emptyFunction)(this); this.run(); } }, run:function(){if(this.isfinished())return(this.options.onComplete||Prototype.emptyFunction);if(this.timer)cleartimout(this.timer);this.duration-=.fps;this.steps--;var pos=1-this.steps/this.steps/this.maxStep;//////////////////////////////////////////////////////////////////////////////////this.loop(this.pos);(this.options options onUpdate|Prototype.emppppp义齿; this.timer = setTimeout(this.run.bind(this), this.fps); }, isFinished: function() { return this.steps <= 0; }, setup:function(effect){//すべての効果ユニットfor(var key in Effect.Init){if(typeof(Effect.Init[key])!=「function」)continue;try{Effect.Init[key](this)}catch(x){}}loop:function(effect,pos){//すべての効果ユニットfor(var key in Effect.Fn){if(typeof(Effect.Fn[key])!="function")continue;try{Effect.Fn[key](effect,pos)}catch(x){}}Effect.Init.opacity=function(effect){ if (effect.options.opacity===undefined) return; effect.setting.opacity=Opacity(effect.element); } Effect.Fn.opacity=function(effect,pos){ if (effect.options.opacity===undefined) return; Opacity(effect.element,effect.setting.opacity+(effect.options.opacity-effect.setting.opacity)*pos); } var foo 1=function()/最も簡単な呼び出し方法new Effect("div 1",{opacity:0.2})}var foo 2=function(){new Effect("{opacity:0.2,delay:3})//遅延3秒}var foo 3=function(){new Effect(",{opacity:0.2,duration:5})/効果実行5秒、デフォルトは2秒です}var foo 4=function()/カスタム関数new Effect("div 1",{opacity:0.2,onStart:function(eff){alert("効果実行時にdocument.titleに注意,実行後にdiv内の文字に注意")},onUpdate:function(eff,p){document.title=p.toFixed(2)}Complete:function(eff){eff.element.innerHTML="実行完了"})}var foo 5=function(){//////先に薄くなってから深くなるnew Effect("div 1",{opacity:0.2,onComplete:function(eff){new Effect({ new Effect( eff.element,{ opacity:1,delay:1})}function foo(){new Effect("div 1",{opacity:1,duration:1})}}}}}}}function foo(){new Effect({ new Effect("div 1",{opacity:1,{opacity:1,duration:}実行foo 1実行foo 2(遅延)実行foo 3(5秒)foo 4(カスタム関数)を実行foo 5(先に薄くしてから深くする)を実行効果を呼び出すたびにポイント下のリカバリボタンでGo_を復元Rush(阿舜)@http://ashun.cnblogs.com/Go_Rush(阿舜)@http://ashun.cnblogs.com/
[Ctrl+A全オプション:外部Jsを導入するにはリフレッシュが必要]
このページはとても长くて、明日新しく1つの随笔をつけて、更に拡张するプラグインsize、move、zoom、colorなどをすべて贴り出して、いくつか模範のコードがあります