X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F02_dom%2F10_XNodeAnime.js;h=2adfebb4584d3c8aa85429e76cbba2267e19b165;hb=4afbf1b687e035eaf2c6b8bbf14e3c443d843d4e;hp=ec0dac9cde6e1e53cbb82f612d728f4dd41f1e2f;hpb=29f2a2e24ee1eea5a80e1345570fd75de6dcdbf4;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/02_dom/10_XNodeAnime.js b/0.6.x/js/02_dom/10_XNodeAnime.js index ec0dac9..2adfebb 100644 --- a/0.6.x/js/02_dom/10_XNodeAnime.js +++ b/0.6.x/js/02_dom/10_XNodeAnime.js @@ -59,6 +59,7 @@ var // アニメ中の remove var X_Node_ANIMATIONS = [], + X_Node_Anime_reserved = false, X_Node_Anime_updateTimerID = 0, X_Node_Anime_needsDetection = false, X_Node_Anime_hasTransform = !!X_Node_CSS_VENDER_PREFIX[ 'transform' ], @@ -67,24 +68,25 @@ var X_Node_ANIMATIONS = [], X_Node_Anime_hasTransition = !!X_Node_CSS_VENDER_PREFIX[ 'transitionDelay' ] && !X.UA.Opera, // Opera12(XP,8.1) 切った方がスムース X_Node_Anime_transitionProps = X_Node_Anime_hasTransform ? X_Node_CSS_VENDER_PREFIX[ 'transform' ] : 'left,top'; +// gpu化だけ transformX , willChange +// 終了位置の変更 +// 中断 + + Node.prototype.animate = function( start, dest, duration, easing, wait ){ - var obj = this._anime || ( this._anime = {} ), current; - - if( X_Node_Anime_hasTransition && this._rawObject ){ - current = {}; //X_Node_Anime_getComputedPosition( this ); - }; + var obj = this._anime || ( this._anime = {} ); - obj.duration = X.Type.isFinite( duration ) && 0 <= duration ? duration : 500; + obj.duration = 0 <= duration && X.Type.isFinite( duration ) ? duration : 500; obj.easing = ease[ easing ] || ease.circular; // 現在 GPUレイヤーのtop になっているか?将来については phase で判定 obj.gpuParent = obj.gpuParent || false; - obj.phase = duration === 0 ? 9 : 0; // + obj.phase = duration === 0 ? 9 : obj.phase === 9 ? 9 : 0; // obj.wait = X.Type.isFinite( wait ) ? wait : 1000; obj.startTime = X_Timer_now(); - obj.startX = ( start.x || start.x === 0 ) ? start.x : obj.x || current && current.x || 0; - obj.startY = ( start.y || start.y === 0 ) ? start.y : obj.y || current && current.y || 0; - obj.startA = 0 <= start.opacity && start.opacity <= 1 ? start.opacity : obj.a || current && current.a || 1; + obj.startX = ( start.x || start.x === 0 ) ? start.x : obj.x || 0; + obj.startY = ( start.y || start.y === 0 ) ? start.y : obj.y || 0; + obj.startA = 0 <= start.opacity && start.opacity <= 1 ? start.opacity : obj.a || 1; obj.destTime = obj.startTime + obj.duration; obj.destX = ( dest.x || dest.x === 0 ) ? dest.x : obj.destX || 0; @@ -99,7 +101,7 @@ Node.prototype.animate = function( start, dest, duration, easing, wait ){ X_Node_Anime_needsDetection = true; if( X_Node_Anime_hasTransition ){ - X_Node_Anime_reserveUpdate(); + X_Node_Anime_reserveUpdate( true ); } else { X_Node_Anime_updateTimerID || ( X_Node_Anime_updateTimerID = X.Timer.requestFrame( X_Node_Anime_updateAnimationsNoTransition ) ); }; @@ -127,19 +129,29 @@ Node.prototype.stop = function(){ return this; }; -function X_Node_Anime_reserveUpdate(){ - if( !X_Node_Anime_updateTimerID ){ - // Opera12 requestAnimationFrame では transition が動かない、、、 - X_Node_Anime_updateTimerID = - X_UA.Opera ? - X.Timer.once( 0, X_Node_Anime_updateAnimations ) : - X.Timer.requestFrame( X_Node_Anime_updateAnimations ); +function X_Node_Anime_reserveUpdate( before ){ + if( !X_Node_Anime_reserved ){ + X_Node_Anime_reserved = true; + + if( X_Node_updateTimerID ){ + console.log( before ? '> BEFORE_UPDATE' : '> UPDATED' ); + X_System.listenOnce( before ? X.Event.BEFORE_UPDATE : X.Event.UPDATED, X_Node_Anime_updateAnimations ); + } else { + console.log( '> Timer' ); + // Opera12 requestAnimationFrame では transition が動かない、、、 + X_Node_Anime_updateTimerID = + X_UA.Opera ? + X.Timer.once( 0, X_Node_Anime_updateAnimations ) : + X.Timer.requestFrame( X_Node_Anime_updateAnimations ); + }; }; }; -function X_Node_Anime_updateAnimations(){ +function X_Node_Anime_updateAnimations( v ){ var i = X_Node_ANIMATIONS.length, ret, c = false; + console.log( v.type || v ); + //console.log( 'updateAnimations ' + i + ' ' + X_Node_Anime_needsDetection ); if( X_Node_Anime_needsDetection ) X_Node_Anime_detectAnimationLayers(); @@ -158,7 +170,10 @@ function X_Node_Anime_updateAnimations(){ }; }; + if( X_Node_Anime_updateTimerID && X_Node_updateTimerID ) X_Node_startUpdate(); + X_Node_Anime_updateTimerID = 0; + X_Node_Anime_reserved = false; if( c ){ X_Node_Anime_reserveUpdate(); }; @@ -168,43 +183,41 @@ function X_Node_Anime_updateAnimations(){ function X_Node_Anime_detectAnimationLayers(){ var i = X_Node_ANIMATIONS.length, l = i, - j, xnode, parent, hasGPUChild, changed, remove; + j, xnode, parent, hasGPUChild, remove; for( ; i; ){ xnode = X_Node_ANIMATIONS[ --i ]; parent = hasGPUChild = false; - //console.log( 'koko- ' + xnode._id + ' ' + xnode._anime.phase ); for( j = l; j; ){ _xnode = X_Node_ANIMATIONS[ --j ]; if( xnode.parent === _xnode.parent ){ - //console.log( 'cont ' + xnode._anime.phase ); continue; } else if( _xnode.contains( xnode ) ){ - if( _xnode._anime.phase === 3 || _xnode._anime.phase === 10 ){ + if( ( _xnode._anime.phase === 3 && _xnode._anime.gpuParent ) || _xnode._anime.phase === 10 ){ _xnode._anime.phase = 15; } else if( xnode._anime.gpuParent ){ - changed = parent = true; + parent = true; xnode._anime.phase = xnode._anime.phase === 2 ? 6 : 15;// GPU レイヤーの解除 > アニメーションは継続, すでに終了フェイズなら破棄 } else if( [ 7, 8, 9, 13, 14 ].indexOf( xnode._anime.phase ) !== -1 ){// GPU レイヤーの中止 - changed = parent = true; + parent = true; xnode._anime.phase -= 8; }; break; } else if( xnode.contains( _xnode ) ){ - if( xnode._anime.phase === 3 || xnode._anime.phase === 10 ){ + if( ( xnode._anime.phase === 3 && xnode._anime.gpuParent ) || xnode._anime.phase === 10 ){ xnode._anime.phase = 15; } else if( _xnode._anime.gpuParent ){ - changed = hasGPUChild = true; + hasGPUChild = true; _xnode._anime.phase = _xnode._anime.phase === 2 ? 6 : 15;// GPU レイヤーの解除 > アニメーションは継続, すでに終了フェイズなら破棄 } else if( [ 7, 8, 9, 13, 14 ].indexOf( _xnode._anime.phase ) !== -1 ){// GPU レイヤーの中止 - changed = hasGPUChild = true; + hasGPUChild = true; _xnode._anime.phase -= 8; }; break; @@ -213,13 +226,10 @@ function X_Node_Anime_detectAnimationLayers(){ if( !parent && xnode._anime.phase !== 15 ){ if( xnode._anime.phase === 0 ){ // 新規 - changed = changed || !xnode._anime.gpuParent; xnode._anime.phase = hasGPUChild ? 7 : 8;// 非GPU -> GPU 子に GPU アニメをもつなら、タイミングをずらす。 } else if( [ 3, 4, 10, 100 ].indexOf( xnode._anime.phase ) === -1 ){ // 非GPU -> GPU - changed = changed || !xnode._anime.gpuParent; - //console.log( 'koko? ' + xnode._anime.phase ); xnode._anime.phase = hasGPUChild ? 13 : 14;// 非GPU -> GPU 子に GPU アニメをもつなら、タイミングをずらす。 }; }; @@ -239,13 +249,14 @@ function X_Node_Anime_updateAnimation( xnode ){ break; case 0 : // 開始位置+アニメーションの設定 case 8 : + X_Node_Anime_readyTransition( xnode ); X_Node_Anime_updatePosition( xnode, obj.startX, obj.startY, obj.startA, phase === 8 ); ++obj.phase; break; case 1 : case 9 : // 終了位置の設定 obj.gpuParent = phase === 9; - X_Node_Anime_updateTransition( xnode, obj.duration, obj.easing ); + obj.duration ? X_Node_Anime_updateTransition( xnode ) : X_Node_Anime_clearTransition( xnode ); X_Node_Anime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, obj.gpuParent ); obj.phase = 2; break; @@ -255,7 +266,7 @@ function X_Node_Anime_updateAnimation( xnode ){ return false; case 3 : // アニメーションの解除 - X_Node_Anime_updateTransition( xnode, 0 ); + X_Node_Anime_clearTransition( xnode ); obj.phase = obj.gpuParent ? 10 : 4; break; @@ -283,7 +294,7 @@ function X_Node_Anime_updateAnimation( xnode ){ now = X_Timer_now(); time = obj.duration - now + obj.startTime; if( time < 16 ){ - X_Node_Anime_updateTransition( xnode, 0 ); + X_Node_Anime_clearTransition( xnode ); X_Node_Anime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, phase === 14 ); obj.phase = phase === 14 ? 10 : 4; } else { @@ -293,7 +304,6 @@ function X_Node_Anime_updateAnimation( xnode ){ obj.startA = current.a; obj.duration = time; obj.startTime = now; - //X_Node_Anime_updateTransition( xnode, time, obj.easing ); X_Node_Anime_updatePosition( xnode, current.x, current.y, current.a, phase === 14 ); obj.phase = phase === 14 ? 9 : 1; }; @@ -302,7 +312,7 @@ function X_Node_Anime_updateAnimation( xnode ){ case 15 : // GPU有効で停止(待機)している xnode の解除 console.log( 'GPU有効で停止(待機)している xnode の解除' + xnode._tag + xnode.getOrder() ); - X_Node_Anime_updateTransition( xnode, 0 ); + X_Node_Anime_clearTransition( xnode ); X_Node_Anime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, false ); obj.gpuTimerID && X.Timer.remove( obj.gpuTimerID ); return true; @@ -311,7 +321,7 @@ function X_Node_Anime_updateAnimation( xnode ){ console.log( 'stop() gpu:' + obj.gpuParent ); current = X_Node_Anime_getComputedPosition( xnode ); - X_Node_Anime_updateTransition( xnode, 0 ); + X_Node_Anime_clearTransition( xnode ); X_Node_Anime_updatePosition( xnode, current.x, current.y, current.a, obj.gpuParent ); obj.phase = obj.gpuParent ? 10 : 4; break; @@ -341,7 +351,7 @@ function X_Node_Anime_onTransitionEnd(){ X_Node_Anime_needsDetection = true; X_Node_Anime_reserveUpdate(); console.log( 'トランジション終了' ); - return X.Callback.UN_LISTEN | X.Callback.PREVENT_DEFAULT; + return X.Callback.UN_LISTEN | X.Callback.PREVENT_DEFAULT | X.Callback.STOP_PROPAGATION; }; function X_Node_Anime_releaseGPULayer(){ @@ -353,22 +363,39 @@ function X_Node_Anime_releaseGPULayer(){ console.log( 'GPUレイヤーの破棄' ); }; -function X_Node_Anime_updateTransition( xnode, time, easing ){ +function X_Node_Anime_readyTransition( xnode ){ + xnode.css({ + willChange : X_Node_Anime_transitionProps + ',opacity,width,height', + backfaceVisibility : 'hidden', + transitionTimingFunction : xnode._anime.easing.style, + transitionDelay : '0s' + }); +}; + +function X_Node_Anime_updateTransition( xnode ){ // 開始座標のセット(新規のみ) // アニメーション指定のセット(または解除)(対象のみ) // 目標座標のセット - if( time ){ - xnode.listenOnce( 'transitionend', X_Node_Anime_onTransitionEnd ); - } else { - xnode.unlisten( 'transitionend', X_Node_Anime_onTransitionEnd ); - }; + xnode.listenOnce( 'transitionend', X_Node_Anime_onTransitionEnd ); + + xnode.css({ + transitionProperty : X_Node_Anime_transitionProps + ',opacity,width,height', + transitionDuration : xnode._anime.duration + 'ms' + }); +}; + +function X_Node_Anime_clearTransition( xnode ){ + // 開始座標のセット(新規のみ) + // アニメーション指定のセット(または解除)(対象のみ) + // 目標座標のセット + xnode.unlisten( 'transitionend', X_Node_Anime_onTransitionEnd ); + xnode.css({ - transitionProperty : X_Node_Anime_transitionProps + ',opacity', - willChange : time ? X_Node_Anime_transitionProps + ',opacity' : '', - backfaceVisibility : time ? 'hidden' : '', - transitionTimingFunction : time ? easing.style : '', - transitionDelay : '0s', - transitionDuration : time ? time + 'ms' : '' + willChange : '', + backfaceVisibility : '', + transitionTimingFunction : '', + transitionDelay : '', + transitionDuration : '' }); };