From: itozyun Date: Wed, 9 Dec 2015 13:55:51 +0000 (+0900) Subject: Version 0.6.200, fix X.Node.Anime. X-Git-Url: http://git.osdn.jp/view?p=pettanr%2FclientJs.git;a=commitdiff_plain;h=d93e0f2faddc687d56a9528402f74ba2415a0407 Version 0.6.200, fix X.Node.Anime. --- diff --git a/0.6.x/img/loading.gif b/0.6.x/img/loading.gif index 2f53369..4c87a7a 100644 Binary files a/0.6.x/img/loading.gif and b/0.6.x/img/loading.gif differ diff --git a/0.6.x/js/02_dom/10_XNodeAnime.js b/0.6.x/js/02_dom/10_XNodeAnime.js index 6ba1bc2..cbf6a33 100644 --- a/0.6.x/js/02_dom/10_XNodeAnime.js +++ b/0.6.x/js/02_dom/10_XNodeAnime.js @@ -41,9 +41,7 @@ var X_NODE_ANIME_RESET = 1, */ function X_Node_animate( start, dest, duration, easing, lazyRelease, option ){ var list = X_NodeAnime_QUEUE, - obj = this[ '_anime' ], - isNew = !obj, - now, stop; + obj = this[ '_anime' ]; if( !( this[ '_flags' ] & X_NodeFlags_IN_TREE ) ){ alert( '@animate 要素はツリーに追加されていません!' ); @@ -51,10 +49,9 @@ function X_Node_animate( start, dest, duration, easing, lazyRelease, option ){ return this; }; - if( isNew ){ + if( !obj ){ this[ '_anime' ] = obj = { x : 0, y : 0, a : 1, - destX : 0, destY : 0, destA : 1, duration : 0 //phase, lazyRelease, easing, follower, releaseNow }; @@ -62,30 +59,27 @@ function X_Node_animate( start, dest, duration, easing, lazyRelease, option ){ if( 0 <= duration && X_Type_isFinite( duration ) ){ obj.duration = duration; - stop = !duration; }; - if( obj.phase !== 7 ){ - // アニメーション中は easing の変更ができない - obj.easing = X_Type_isFunction( easing ) ? easing : X_NodeAnime_ease[ easing ] || X_NodeAnime_ease[ 'circular' ]; - }; + obj.easing = X_Type_isFunction( easing ) ? easing : X_NodeAnime_ease[ easing ] || X_NodeAnime_ease[ 'circular' ]; + // form : obj.startX = obj.x = X_NodeAnime_getFinite( start[ 'x' ], obj.x ); obj.startY = obj.y = X_NodeAnime_getFinite( start[ 'y' ], obj.y ); obj.startA = obj.a = X_NodeAnime_getFinite( start[ 'opacity' ], obj.a ); // to : - obj.destX = X_NodeAnime_getFinite( dest[ 'x' ], obj.destX ); - obj.destY = X_NodeAnime_getFinite( dest[ 'y' ], obj.destY ); - obj.destA = X_NodeAnime_getFinite( dest[ 'opacity' ], obj.destA ); + obj.destX = X_NodeAnime_getFinite( dest[ 'x' ], obj.x ); + obj.destY = X_NodeAnime_getFinite( dest[ 'y' ], obj.y ); + obj.destA = X_NodeAnime_getFinite( dest[ 'opacity' ], obj.a ); obj.lazyRelease = 0 <= lazyRelease && X_Type_isFinite( lazyRelease ) ? lazyRelease : 0; + obj.inited = false; - if( stop && 6 <= obj.phase ){ + if( !obj.duration && 6 <= obj.phase ){ this[ 'stop' ](); // 現在値で停止 - } else - if( !stop || obj.lazyRelease ){ - if( isNew || !obj.phase ){ + } else { + if( !obj.phase ){ list[ list.length ] = this; obj.phase = 1; obj.uid = ++X_NodeAnime_uid; @@ -97,14 +91,14 @@ function X_Node_animate( start, dest, duration, easing, lazyRelease, option ){ obj.uid = ++X_NodeAnime_uid; X_NodeAnime_needsDetection = true; } else - if( !stop ){ + if( obj.duration ){ // リストの先頭にいるため検査不要でアニメーション開始可能 4, 5, 6, 7 obj.phase = 6; } else - // obj.lazyRelease はあり + // GPU 転送予約、または transform や opacity の値のみ設定 if( obj.phase !== 5 ){ // GPU解除待ち ではない -> 4. 6, 7 - obj.phase = 4; // 強制停止(GPU転送予約) - obj.releaseNow = false; // TODO folower が要るため GPU 転送できないケースあり + obj.phase = 4; // 強制停止(GPU転送予約)または値のみ更新 + obj.releaseNow = false; // TODO folower がいるため GPU 転送できないケースあり X_NodeAnime_needsDetection = true; }; @@ -120,11 +114,6 @@ function X_Node_animate( start, dest, duration, easing, lazyRelease, option ){ X_NodeAnime_updateTimerID = X_Timer_requestFrame( X_NodeAnime_updateAnimations ); }; }; - } else { - if( obj.phase ){ - this[ 'stop' ](); // リストから外す - }; - console.log( 'リストに加えない!' ); }; return this; @@ -167,6 +156,8 @@ function X_Node_stop( option ){ obj.startA = obj.destA = obj.a = 1; }; // TODO 終了値で停止も,,, + // obj.canceled = true; + if( rm ) break; // 1,2,3,6 の場合ここまで obj.destX = obj.x; @@ -188,12 +179,34 @@ function X_Node_stop( option ){ return this; }; +/* + * remove(append swap 等でない部的に呼ばれている場合も), kill 時に + */ +function X_NodeAnime_stopNow( xnode ){ + var obj = xnode[ '_anime' ], + flags = xnode[ '_flags' ], + list = X_NodeAnime_QUEUE, + skipUpdate; + + // if( !obj || !obj.phase ) return; 呼び出し側で検証済 + + X_NodeAnime_needsDetection = true; + list.splice( list.indexOf( xnode ), 1 ); + obj.phase = 0; + + // この部分 startUpdate へ? + if( flags & ~X_Node_BitMask_RESET_GPU ){ + skipUpdate = flags & X_NodeFlags_GPU_RESERVED; + ( flags & X_NodeFlags_GPU_RELEASE_RESERVED ) || X_NodeAnime_updatePosition( xnode, obj.x, obj.y, obj.a, false ); + skipUpdate || ( xnode[ '_rawObject' ].style.cssText = X_Node_CSS_objToCssText( xnode ) ); + xnode[ '_flags' ] &= X_Node_BitMask_RESET_GPU; + }; +}; /* * 1. 新規アニメーションが現在アニメーション中の要素の親か子であればアニメーションを待機 - * 2. */ -function X_NodeAnime_detectWaitAnimation( xnode, duration, isText ){ +function X_NodeAnime_detectWaitAnimation( xnode, duration, isTest ){ var list = X_NodeAnime_QUEUE, i = 0, _xnode; @@ -203,7 +216,7 @@ function X_NodeAnime_detectWaitAnimation( xnode, duration, isText ){ // アニメーションの優先度はリストにいる順 // まず先行する後続待機要素の中に、親子関係のものがいないか?探す if( _xnode[ '_anime' ].phase <= 3 ){ - if( xnode[ 'contains' ]( _xnode ) || _xnode[ 'contains' ]( xnode ) ){ + if( xnode[ 'contains' ]( _xnode ) || _xnode[ 'contains' ]( xnode ) ){ // 祖先か?見た方が早そう // -> いる、このような要素が複数いる場合、誰に後続すればいいか?判然としないため、準待機フラグを立てる return 2; }; @@ -218,7 +231,7 @@ function X_NodeAnime_detectWaitAnimation( xnode, duration, isText ){ if( 6 <= _xnode[ '_anime' ].phase ){ if( xnode[ 'contains' ]( _xnode ) || _xnode[ 'contains' ]( xnode ) ){ - return isText ? 3 : _xnode; + return isTest ? 3 : _xnode; }; }; }; @@ -228,17 +241,16 @@ function X_NodeAnime_detectWaitAnimation( xnode, duration, isText ){ function X_NodeAnime_updateAnimations( e ){ var list = X_NodeAnime_QUEUE, - i = list.length, now = X_Timer_now(), - c = false, + c = false, i, xnode, obj, _xnode, - rm, easing, follower, lazy; + rm, easing, lazy; if( X_NodeAnime_needsDetection ){ X_NodeAnime_needsDetection = false; // - list.sort( X_NodeAnime_sortAnimationNode ); + list.sort( X_NodeAnime_sortAnimationNode ); for( i = 0; xnode = list[ i ]; ++i ){ obj = xnode[ '_anime' ]; @@ -254,7 +266,7 @@ function X_NodeAnime_updateAnimations( e ){ }; }; - for( ; i; ){ + for( i = list.length; i; ){ rm = false; xnode = list[ --i ]; obj = xnode[ '_anime' ]; @@ -271,11 +283,17 @@ function X_NodeAnime_updateAnimations( e ){ break; }; // アニメーション終了 + xnode[ 'asyncDispatch' ]( X_EVENT_ANIME_END ); + case 4 : // 強制停止(GPU転送予約) lazy = !obj.follower && !obj.releaseNow && obj.lazyRelease; X_NodeAnime_updatePosition( xnode, obj.destX, obj.destY, obj.destA, !!lazy ); - xnode[ 'asyncDispatch' ]( X_EVENT_ANIME_END ); + //if( obj.canceled ){ + // xnode[ 'asyncDispatch' ]( X_EVENT_CANCELED ); + //} else { + + //}; if( lazy ){ console.log( 'アニメーション終了(' + obj.phase + ') -> GPU 解除待機 ' + lazy ); @@ -292,10 +310,11 @@ function X_NodeAnime_updateAnimations( e ){ obj.startTime = now; obj.destTime = now + obj.duration; obj.phase = 7; // アニメーション中 - obj.progress = 0; - X_NodeAnime_updatePosition( xnode, obj.startX, obj.startY, obj.startA, true ); + obj.progress = 0; xnode[ 'asyncDispatch' ]( X_EVENT_ANIME_START ); c = true; + //obj.canceled = false; + ( obj.inited && !X_NodeAnime_translateZ ) || X_NodeAnime_updatePosition( xnode, obj.startX, obj.startY, obj.startA, true ); break; case 5 : // GPU解除待ち @@ -305,7 +324,13 @@ function X_NodeAnime_updateAnimations( e ){ } else { c = true; }; - break; + break; + + default : // 2 or 3 + // 待機状態でも親要素が GPU 化していなければ、開始値をセットすることは可能 + obj.inited || X_NodeAnime_updatePosition( xnode, obj.startX, obj.startY, obj.startA, false ); + obj.inited = false; + break; }; obj.releaseNow = false; diff --git a/0.6.x/js/02_dom/20_XNode.js b/0.6.x/js/02_dom/20_XNode.js index e40f832..ab4e26b 100644 --- a/0.6.x/js/02_dom/20_XNode.js +++ b/0.6.x/js/02_dom/20_XNode.js @@ -781,12 +781,13 @@ function X_Node_remove(){ if( !parent ) return this; - // TODO anime // stop() -> if( this[ '_anime' ] && this[ '_anime' ].phase ){ console.log( 'Animation 中の REMOVE' ); - this[ 'stop' ](); + X_NodeAnime_stopNow( this ); }; + // 子孫にアニメーション中の要素が要る + // 先祖に GPU 化した要素が要る delete this.parent; parent[ '_xnodes' ].splice( parent[ '_xnodes' ].indexOf( this ), 1 ); @@ -798,7 +799,7 @@ function X_Node_remove(){ if( X_UA_DOM.IE4 ){ if( elm = this[ '_rawObject' ] || X_Node__ie4getRawNode( this ) ){ X_Node_reserveRemoval[ X_Node_reserveRemoval.length ] = this; - X_Node_reserveUpdate(); + X_Node_reserveUpdate(); } else if( !this[ '_tag' ] && ( ( parent[ '_flags' ] & X_NodeFlags_IE4_FIXED ) === 0 ) ){ parent[ '_flags' ] |= X_NodeFlags_IE4_DIRTY_CHILDREN; @@ -849,8 +850,6 @@ function X_Node_onKill( that ){ parent && parent[ '_xnodes' ] && parent[ '_xnodes' ].splice( parent[ '_xnodes' ].indexOf( that ), 1 ); - elm = that[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( that ); - if( xnodes && ( i = xnodes.length ) ){ delete that[ '_xnodes' ]; for( ; i; ){ @@ -861,12 +860,13 @@ function X_Node_onKill( that ){ X_Node_CHASHE[ that[ '_uid' ] ] = null; // array に対して delete X_Node_CHASHE[ uid ] はまずい! -// TODO anime if( that[ '_anime' ] && that[ '_anime' ].phase ){ console.log( 'Animation 中の KILL' ); - that[ 'stop' ](); + X_NodeAnime_stopNow( that ); }; + elm = that[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( that ); + // remove _xnodes if( X_UA_DOM.IE4 ){ if( elm ){ @@ -895,26 +895,15 @@ function X_Node_onKill( that ){ * @example node.contains( testNode ); */ function X_Node_contains( v ){ - var elm, type, xnodes, i; + var xnodes; if( !v || !this[ '_tag' ] || this === v ) return false; - - // contains ie4+ - /* - if( ( elm = this[ '_rawObject' ] || X_UA_DOM.IE4 && X_Node__ie4getRawNode( this ) ) && document.contains && ( type = X_Node_getType( v ) ) && ( type === X_NodeType_RAW_HTML || type === X_NodeType_RAW_TEXT ) ){ - return elm.contains( v ); - }; */ - //if( document.compareDocumentPosition ){ - // - //}; - xnodes = this[ '_xnodes' ]; if( !xnodes || !xnodes.length ) return false; - if( this === v[ 'parent' ] ) return true; // fast - if( xnodes.indexOf( v ) !== -1 ) return true; // fast - for( i = xnodes.length; i; ){ - if( xnodes[ --i ][ 'contains' ]( v ) ) return true; + + while( v = v[ 'parent' ] ){ + if( this === v ) return true; }; return false; }; @@ -1237,6 +1226,17 @@ function X_Node_call( name /*, opt_args... */ ){ return this.parent ? X_Node_CSS_getCharSize( this ) : 0; case 'inGPU' : return !!( this[ '_flags' ] & ( X_NodeFlags_GPU_NOW | X_NodeFlags_GPU_RELEASE_RESERVED ) ); + case 'isGPUChild' : + if( this[ '_flags' ] & X_NodeFlags_IN_TREE ){ + parent = this; + while( parent = parent.parent ){ + if( parent[ '_flags' ] & ( X_NodeFlags_GPU_NOW | X_NodeFlags_GPU_RELEASE_RESERVED ) ) return true; + }; + }; + return false; + case 'containGPU' : + + return false; case 'canAnimateNow' : return ( this[ '_flags' ] & X_NodeFlags_IN_TREE ) && X_NodeAnime_detectWaitAnimation( this, true, true ) === 6; case 'animeState' : @@ -1460,12 +1460,12 @@ var X_Node__commitUpdate = console.log( 'GPU 解放 ' ); //X_Node_updateReservedByReleaseGPU = true; that[ '_flags' ] &= X_Node_BitMask_RESET_GPU; - //return elm;// TODO もしかしたらこのタイミングで更新できるかも。 + //return elm;// このタイミングで更新できるっぽい。 }; // 3. GPU予約 -> GPU if( that[ '_flags' ] & X_NodeFlags_GPU_RESERVED ){ - // TODO size 取得のための update の場合、GPU化を待つ + // TODO size 取得のための update の場合、GPU化をスキップ that[ '_flags' ] &= X_Node_BitMask_RESET_GPU; that[ '_flags' ] |= X_NodeFlags_GPU_NOW; }; @@ -1518,7 +1518,7 @@ var X_Node__commitUpdate = if( that[ '_flags' ] & X_NodeFlags_IS_SVG ){ elm = document.createElementNS( 'http://www.w3.org/2000/svg', that[ '_tag' ].toLowerCase() ); - // math http://www.w3.org/1998/Math/MathML + // TODO math http://www.w3.org/1998/Math/MathML } else { elm = document.createElement( that[ '_tag' ] ); }; diff --git a/0.6.x/js/20_ui/15_ScrollBox.js b/0.6.x/js/20_ui/15_ScrollBox.js index 9a93207..1770704 100644 --- a/0.6.x/js/20_ui/15_ScrollBox.js +++ b/0.6.x/js/20_ui/15_ScrollBox.js @@ -597,11 +597,7 @@ function X_UI_ScrollBox_resetPosition( that, time ){ }; function X_UI_ScrollBox_onAnimeEnd( e ){ - if( e.target !== this.xnodeSlider ){ - console.log( '- not much -' ); - console.dir(e); - }; - if( e.target === this.xnodeSlider && this.isInTransition && !X_UI_ScrollBox_resetPosition( this, this.bounceTime ) ){ + if( this.isInTransition && !X_UI_ScrollBox_resetPosition( this, this.bounceTime ) ){ this.isInTransition = false; //console.log( '-2-' ); this[ 'dispatch' ]( XUI_Event.SCROLL_END );