handle bidirectional transitions differently

pull/525/head
Rich-Harris 8 years ago
parent aa67f8b8c4
commit 45a9ce056d

@ -21,6 +21,7 @@
"build:shared": "rollup -c rollup/rollup.config.shared.js",
"build:ssr": "rollup -c rollup/rollup.config.ssr.js",
"dev": "rollup -c rollup/rollup.config.main.js -w",
"dev:shared": "rollup -c rollup/rollup.config.shared.js -w",
"pretest": "npm run build",
"prepublish": "npm run lint && npm run build"
},

@ -159,7 +159,7 @@ export default function dom ( parsed, source, options ) {
` );
}
if ( generator.hasComponents ) {
if ( generator.hasComponents || generator.hasIntroTransitions ) {
const statement = `this._flush();`;
builders.init.addBlock( statement );

@ -62,7 +62,7 @@ export default function visitElement ( generator, block, state, node ) {
visitors[ attribute.type ]( generator, block, childState, node, attribute );
});
addTransitions( generator, block, childState, node, intro, outro );
if ( intro || outro ) addTransitions( generator, block, childState, node, intro, outro );
if ( !outro && !state.parentNode ) {
// TODO this probably doesn't belong here. We eventually need to consider

@ -1,52 +1,77 @@
import deindent from '../../../../utils/deindent.js';
export default function addTransitions ( generator, block, state, node, intro, outro ) {
const introName = intro && block.getUniqueName( `${state.name}_intro` );
const outroName = outro && block.getUniqueName( `${state.name}_outro` );
const introSnippet = intro && intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
const outroSnippet = outro === intro ?
introSnippet :
outro && outro.expression ? block.contextualise( outro.expression ).snippet : '{}';
const wrapTransition = generator.helper( 'wrapTransition' );
if ( intro ) {
block.addVariable( introName );
if ( intro === outro ) {
const name = block.getUniqueName( `${state.name}_transition` );
const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`; // TODO add built-in transitions?
block.addVariable( name );
if ( outro ) {
block.builders.intro.addBlock( `if ( ${outroName} ) ${outroName}.abort();` );
}
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`;
block.builders.intro.addBlock( deindent`
${block.component}._renderHooks.push( function () {
${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${introSnippet}, true, null, function () {
if ( !${name} ) ${name} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
${name}.run( ${name}.t, 1, function () {
${block.component}.fire( 'intro.end', { node: ${state.name} });
});
${generator.helper( 'transitionManager' )}.add( ${introName} );
});
` );
}
if ( outro ) {
block.addVariable( outroName );
const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`;
if ( intro ) {
block.builders.outro.addBlock( `${introName}.abort();` );
}
block.builders.outro.addBlock( deindent`
${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${outroSnippet}, false, null, function () {
detachNode( div );
${name}.run( ${name}.t, 0, function () {
detachNode( ${state.name} );
${block.component}.fire( 'outro.end', { node: ${state.name} });
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
${name} = null;
});
transitionManager.add( ${outroName} );
` );
}
else {
const introName = intro && block.getUniqueName( `${state.name}_intro` );
const outroName = outro && block.getUniqueName( `${state.name}_outro` );
if ( intro ) {
block.addVariable( introName );
const snippet = intro.expression ? block.contextualise( intro.expression ).snippet : '{}';
const fn = `${generator.alias( 'template' )}.transitions.${intro.name}`; // TODO add built-in transitions?
if ( outro ) {
block.builders.intro.addBlock( `if ( ${outroName} ) ${outroName}.abort();` );
}
block.builders.intro.addBlock( deindent`
${block.component}._renderHooks.push( function () {
${introName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, true, null );
${introName}.run( 0, 1, function () {
${block.component}.fire( 'intro.end', { node: ${state.name} });
});
});
` );
}
if ( outro ) {
block.addVariable( outroName );
const snippet = outro.expression ? block.contextualise( outro.expression ).snippet : '{}';
const fn = `${generator.alias( 'template' )}.transitions.${outro.name}`;
if ( intro ) {
block.builders.outro.addBlock( `${introName}.abort();` );
}
block.builders.outro.addBlock( deindent`
${outroName} = ${wrapTransition}( ${state.name}, ${fn}, ${snippet}, false, null );
${outroName}.run( 1, 0, function () {
detachNode( ${state.name} );
${block.component}.fire( 'outro.end', { node: ${state.name} });
if ( --${block.alias( 'outros' )} === 0 ) ${block.alias( 'outrocallback' )}();
});
` );
}
}
}

@ -4,12 +4,10 @@ export function linear ( t ) {
return t;
}
export function wrapTransition ( node, fn, params, intro, outgroup, callback ) {
export function wrapTransition ( node, fn, params, intro, outgroup ) {
var obj = fn( node, params, intro );
var start = window.performance.now() + ( obj.delay || 0 );
var duration = obj.duration || 300;
var end = start + duration;
var ease = obj.easing || linear;
if ( obj.tick ) {
@ -17,19 +15,40 @@ export function wrapTransition ( node, fn, params, intro, outgroup, callback ) {
if ( intro ) obj.tick( 0 );
return {
start: start,
end: end,
start: null,
end: null,
a: null,
d: null,
running: false,
t: intro ? 0 : 1,
callback: null,
update: function ( now ) {
const p = intro ? now - start : end - now;
obj.tick( ease( p / duration ) );
const p = now - this.start;
this.t = this.a + this.d * ease( p / this.duration );
obj.tick( this.t );
},
done: function () {
obj.tick( intro ? 1 : 0 );
callback();
this.callback();
this.running = false;
},
abort: function () {
if ( !intro ) obj.tick( 1 ); // reset styles for intro
this.aborted = true;
this.running = false;
},
run: function ( a, b, callback ) {
this.a = a;
this.d = 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 ( !this.running ) {
this.running = true;
transitionManager.add( this );
}
}
};
} else {
@ -75,6 +94,9 @@ export function wrapTransition ( node, fn, params, intro, outgroup, callback ) {
abort: function () {
node.style.cssText = getComputedStyle( node ).cssText;
this.aborted = true;
},
run: function ( a, b, callback ) {
// TODO...
}
};
}
@ -110,11 +132,17 @@ export var transitionManager = {
while ( i-- ) {
var transition = transitionManager.transitions[i];
if ( now < transition.end && !transition.aborted ) {
if ( now > transition.start ) transition.update( now );
if ( transition.running ) {
if ( now >= transition.end ) {
transition.done();
} else if ( now > transition.start ) {
transition.update( now );
}
}
if ( transition.running ) {
transitionManager.running = true;
} else {
if ( !transition.aborted ) transition.done();
transitionManager.transitions.splice( i, 1 );
}
}

Loading…
Cancel
Save