0
0
mirror of https://github.com/sveltejs/svelte.git synced 2024-12-01 17:30:59 +01:00

CSS transitions

This commit is contained in:
Rich-Harris 2017-04-30 16:06:36 -04:00
parent 45a9ce056d
commit 806b09840a

View File

@ -1,4 +1,4 @@
import { noop } from './utils.js';
import { assign, noop } from './utils.js';
export function linear ( t ) {
return t;
@ -10,18 +10,39 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) {
var duration = obj.duration || 300;
var ease = obj.easing || linear;
var transition = {
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.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 ( !obj.tick ) this.generateKeyframes();
if ( !this.running ) {
this.running = true;
transitionManager.add( this );
}
}
}
if ( obj.tick ) {
// JS transition
if ( intro ) obj.tick( 0 );
return {
start: null,
end: null,
a: null,
d: null,
running: false,
t: intro ? 0 : 1,
callback: null,
return assign( transition, {
update: function ( now ) {
const p = now - this.start;
this.t = this.a + this.d * ease( p / this.duration );
@ -30,76 +51,58 @@ export function wrapTransition ( node, fn, params, intro, outgroup ) {
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 ) {
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 {
// 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
for ( var key in obj.styles ) {
node.style[ key ] = intro ? computedStyles[ key ] : obj.styles[ key ];
}
started = true;
}
},
done: function () {
// TODO what if one of these styles was dynamic?
if ( intro ) {
for ( var key in obj.styles ) {
node.style[ key ] = inlineStyles[ key ];
}
}
callback();
},
abort: function () {
node.style.cssText = getComputedStyle( node ).cssText;
this.aborted = true;
},
run: function ( a, b, callback ) {
// TODO...
}
};
});
}
// CSS transition
var started = false;
var id = null;
var style = document.createElement( 'style' );
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 () {
this.callback();
cleanup();
},
abort: function () {
cleanup();
}
});
}
export var transitionManager = {
@ -134,13 +137,12 @@ export var transitionManager = {
if ( transition.running ) {
if ( now >= transition.end ) {
transition.running = false;
transition.done();
} else if ( now > transition.start ) {
transition.update( now );
}
}
if ( transition.running ) {
transitionManager.running = true;
} else {
transitionManager.transitions.splice( i, 1 );