CSS transitions

pull/525/head
Rich-Harris 9 years ago
parent 45a9ce056d
commit 806b09840a

@ -1,4 +1,4 @@
import { noop } from './utils.js'; import { assign, noop } from './utils.js';
export function linear ( t ) { export function linear ( t ) {
return t; return t;
@ -10,34 +10,18 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) {
var duration = obj.duration || 300; var duration = obj.duration || 300;
var ease = obj.easing || linear; var ease = obj.easing || linear;
if ( obj.tick ) { var transition = {
// JS transition
if ( intro ) obj.tick( 0 );
return {
start: null, start: null,
end: null, end: null,
a: null, a: null,
b: null,
d: null, d: null,
running: false, running: false,
t: intro ? 0 : 1, t: intro ? 0 : 1,
callback: null, callback: null,
update: function ( now ) {
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 );
this.callback();
this.running = false;
},
abort: function () {
if ( !intro ) obj.tick( 1 ); // reset styles for intro
this.running = false;
},
run: function ( a, b, callback ) { run: function ( a, b, callback ) {
this.a = a; this.a = a;
this.b = b;
this.d = b - a; this.d = b - a;
this.start = window.performance.now() + ( obj.delay || 0 ); this.start = window.performance.now() + ( obj.delay || 0 );
this.duration = duration * Math.abs( b - a ); this.duration = duration * Math.abs( b - a );
@ -45,61 +29,80 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) {
this.callback = callback; this.callback = callback;
if ( !obj.tick ) this.generateKeyframes();
if ( !this.running ) { if ( !this.running ) {
this.running = true; this.running = true;
transitionManager.add( this ); transitionManager.add( this );
} }
} }
};
} else {
// CSS transition
var started = false;
var inlineStyles = {};
var computedStyles = getComputedStyle( node );
return {
start: start,
end: end,
init: function () {
for ( var key in obj.styles ) {
inlineStyles[ key ] = node.style[ key ];
node.style[ key ] = intro ? obj.styles[ key ] : computedStyles[ key ];
} }
},
update: function ( now ) {
if ( !started ) {
var keys = Object.keys( obj.styles );
div.style.transition = keys.map( function ( key ) {
return key + ' ' + d;
}).join( ', ' );
// TODO use a keyframe animation for custom easing functions if ( obj.tick ) {
// JS transition
if ( intro ) obj.tick( 0 );
for ( var key in obj.styles ) { return assign( transition, {
node.style[ key ] = intro ? computedStyles[ key ] : obj.styles[ key ]; update: function ( now ) {
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 );
this.callback();
},
abort: function () {
if ( !intro ) obj.tick( 1 ); // reset styles for intro
this.running = false;
} }
});
}
// CSS transition
var started = false;
var id = null;
var style = document.createElement( 'style' );
started = true; var cleanup = function () {
document.head.removeChild( style );
transition.running = started = false;
};
return assign( transition, {
generateKeyframes: function () {
id = 'svelte_' + ~~( Math.random() * 1e9 ); // TODO make this more robust
var keyframes = '@keyframes ' + id + '{\n';
for ( var p = 0; p <= 1; p += 166.666 / this.duration ) {
var t = this.a + this.d * ease( p );
var styles = obj.styles( ease( t ) );
keyframes += ( p * 100 ) + '%{' + styles + '}\n';
} }
keyframes += '100% {' + obj.styles( this.b ) + '}\n}';
style.textContent = keyframes;
document.head.appendChild( style );
node.style.animationName = id;
node.style.animationDuration = ( this.duration / 1e3 ) + 's';
node.style.animationTimingFunction = 'linear';
node.style.animationIterationCount = 1;
node.style.animationFillMode = 'forwards';
},
update: function ( now ) {
const p = now - this.start;
this.t = this.a + this.d * ease( p / this.duration );
}, },
done: function () { done: function () {
// TODO what if one of these styles was dynamic? this.callback();
if ( intro ) { cleanup();
for ( var key in obj.styles ) {
node.style[ key ] = inlineStyles[ key ];
}
}
callback();
}, },
abort: function () { abort: function () {
node.style.cssText = getComputedStyle( node ).cssText; cleanup();
this.aborted = true;
},
run: function ( a, b, callback ) {
// TODO...
}
};
} }
});
} }
export var transitionManager = { export var transitionManager = {
@ -134,13 +137,12 @@ export var transitionManager = {
if ( transition.running ) { if ( transition.running ) {
if ( now >= transition.end ) { if ( now >= transition.end ) {
transition.running = false;
transition.done(); transition.done();
} else if ( now > transition.start ) { } else if ( now > transition.start ) {
transition.update( now ); transition.update( now );
} }
}
if ( transition.running ) {
transitionManager.running = true; transitionManager.running = true;
} else { } else {
transitionManager.transitions.splice( i, 1 ); transitionManager.transitions.splice( i, 1 );

Loading…
Cancel
Save