diff --git a/src/generators/dom/visitors/Element/addTransitions.js b/src/generators/dom/visitors/Element/addTransitions.js index e7fda98331ba..6a5953d02ce2 100644 --- a/src/generators/dom/visitors/Element/addTransitions.js +++ b/src/generators/dom/visitors/Element/addTransitions.js @@ -14,14 +14,14 @@ export default function addTransitions ( generator, block, state, node, intro, o block.builders.intro.addBlock( deindent` ${block.component}._renderHooks.push( function () { if ( !${name} ) ${name} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null ); - ${name}.run( ${name}.t, 1, function () { + ${name}.run( true, function () { ${block.component}.fire( 'intro.end', { node: ${state.name} }); }); }); ` ); block.builders.outro.addBlock( deindent` - ${name}.run( ${name}.t, 0, function () { + ${name}.run( false, function () { ${block.component}.fire( 'outro.end', { node: ${state.name} }); if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}(); ${name} = null; @@ -49,7 +49,7 @@ export default function addTransitions ( generator, block, state, node, intro, o block.builders.intro.addBlock( deindent` ${block.component}._renderHooks.push( function () { ${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null ); - ${introName}.run( 0, 1, function () { + ${introName}.run( true, function () { ${block.component}.fire( 'intro.end', { node: ${state.name} }); }); }); @@ -66,7 +66,7 @@ export default function addTransitions ( generator, block, state, node, intro, o // group) prior to their removal from the DOM block.builders.outro.addBlock( deindent` ${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null ); - ${outroName}.run( 1, 0, function () { + ${outroName}.run( false, function () { ${block.component}.fire( 'outro.end', { node: ${state.name} }); if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}(); }); diff --git a/src/shared/transitions.js b/src/shared/transitions.js index 289ded618220..916a69b3ddc0 100644 --- a/src/shared/transitions.js +++ b/src/shared/transitions.js @@ -28,7 +28,7 @@ export function generateKeyframes ( a, b, delta, duration, ease, fn, node, style } export function wrapTransition ( node, fn, params, intro, outgroup ) { - var obj = fn( node, params, intro ); + var obj = fn( node, params ); var duration = obj.duration || 300; var ease = obj.easing || linear; @@ -40,26 +40,21 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) { if ( intro && obj.tick ) obj.tick( 0 ); return { - start: null, - end: null, - a: null, - b: null, - d: null, - running: false, t: intro ? 0 : 1, - callback: null, - run: function ( a, b, callback ) { - this.a = a; - this.b = b; - this.delta = b - a; - this.start = window.performance.now() + ( obj.delay || 0 ); - this.duration = duration * Math.abs( b - a ); - this.end = this.start + this.duration; - - this.callback = callback; - - if ( obj.css ) { - generateKeyframes( this.a, this.b, this.delta, this.duration, ease, obj.css, node, style ); + running: false, + program: null, + pending: null, + run: function ( intro, callback ) { + var program = { + start: window.performance.now() + ( obj.delay || 0 ), + intro: intro, + callback: callback + }; + + if ( obj.delay ) { + this.pending = program; + } else { + this.start( program ); } if ( !this.running ) { @@ -67,20 +62,40 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) { transitionManager.add( this ); } }, + start: function ( program ) { + program.a = this.t; + program.b = program.intro ? 1 : 0; + program.delta = program.b - program.a; + program.duration = duration * Math.abs( program.b - program.a ); + program.end = program.start + program.duration; + + if ( obj.css ) { + generateKeyframes( program.a, program.b, program.delta, program.duration, ease, obj.css, node, style ); + } + + this.program = program; + this.pending = null; + }, update: function ( now ) { - var p = now - this.start; - this.t = this.a + this.delta * ease( p / this.duration ); + var program = this.program; + if ( !program ) return; + + var p = now - program.start; + this.t = program.a + program.delta * ease( p / program.duration ); if ( obj.tick ) obj.tick( this.t ); }, done: function () { - if ( obj.tick ) obj.tick( intro ? 1 : 0 ); + this.t = this.program.b; + if ( obj.tick ) obj.tick( this.t ); if ( obj.css ) document.head.removeChild( style ); - this.callback(); - this.running = false; + this.program.callback(); + this.program = null; + this.running = !!this.pending; }, abort: function () { if ( obj.tick ) obj.tick( 1 ); if ( obj.css ) document.head.removeChild( style ); + this.program = this.pending = null; this.running = false; } }; @@ -108,16 +123,18 @@ export var transitionManager = { while ( i-- ) { var transition = transitionManager.transitions[i]; - if ( transition.running ) { - if ( now >= transition.end ) { - transition.running = false; - transition.done(); - } else if ( now > transition.start ) { - transition.update( now ); - } + if ( transition.program && now >= transition.program.end ) { + transition.done(); + } + + if ( transition.pending && now >= transition.pending.start ) { + transition.start( transition.pending ); + } + if ( transition.running ) { + transition.update( now ); transitionManager.running = true; - } else { + } else if ( !transition.pending ) { transitionManager.transitions.splice( i, 1 ); } } diff --git a/test/runtime/samples/transition-js-delay-in-out/_config.js b/test/runtime/samples/transition-js-delay-in-out/_config.js new file mode 100644 index 000000000000..6e97f19c3b2e --- /dev/null +++ b/test/runtime/samples/transition-js-delay-in-out/_config.js @@ -0,0 +1,24 @@ +export default { + test ( assert, component, target, window, raf ) { + component.set({ visible: true }); + const div = target.querySelector( 'div' ); + assert.equal( div.foo, 0 ); + + raf.tick( 50 ); + assert.equal( div.foo, 0 ); + + raf.tick( 150 ); + assert.equal( div.foo, 1 ); + + component.set({ visible: false }); + assert.equal( div.bar, undefined ); + + raf.tick( 200 ); + assert.equal( div.bar, 1 ); + + raf.tick( 300 ); + assert.equal( div.bar, 0 ); + + component.destroy(); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/transition-js-delay-in-out/main.html b/test/runtime/samples/transition-js-delay-in-out/main.html new file mode 100644 index 000000000000..6a0a3f88a7ae --- /dev/null +++ b/test/runtime/samples/transition-js-delay-in-out/main.html @@ -0,0 +1,29 @@ +{{#if visible}} +