small refactor, fix in-out-in transitions

pull/1971/head
Richard Harris 7 years ago
parent 1f6d0221e2
commit 7f258bec71

@ -26,15 +26,8 @@ export function animate(node, from, fn, params) {
function start() {
if (css) {
if (delay) node.style.cssText = cssText;
name = create_rule(0, 1, duration, easing, css);
node.style.animation = (node.style.animation || '')
.split(', ')
.filter(anim => anim && !/__svelte/.test(anim))
.concat(`${name} ${duration}ms linear 1 forwards`)
.join(', ');
if (delay) node.style.cssText = cssText; // TODO create delayed animation instead?
name = create_rule(node, 0, 1, duration, 0, easing, css);
}
started = true;

@ -13,7 +13,7 @@ function hash(str) {
return hash >>> 0;
}
export function create_rule(a, b, duration, ease, fn) {
export function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
const step = 16.666 / duration;
let keyframes = '{\n';
@ -23,7 +23,7 @@ export function create_rule(a, b, duration, ease, fn) {
}
const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
const name = `__svelte_${hash(rule)}`;
const name = `__svelte_${hash(rule)}_${uid}`;
if (!current_rules[name]) {
if (!stylesheet) {
@ -36,14 +36,20 @@ export function create_rule(a, b, duration, ease, fn) {
stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
}
const animation = node.style.animation || '';
node.style.animation = `${animation ? `${animation}, ` : ``}${name} ${duration}ms linear ${delay}ms 1 both`;
active += 1;
return name;
}
export function delete_rule(node, name) {
node.style.animation = node.style.animation
node.style.animation = (node.style.animation || '')
.split(', ')
.filter(anim => anim.indexOf(name) < 0)
.filter(name
? anim => anim.indexOf(name) < 0 // remove specific animation
: anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations
)
.join(', ');
if (!--active) clear_rules();

@ -1,6 +1,6 @@
import { identity as linear, noop, run, run_all } from './utils.js';
import { loop } from './loop.js';
import { create_rule, delete_rule } from './style_manager.js';
import { create_rule, delete_rule, delete_rules } from './style_manager.js';
let promise;
@ -39,6 +39,7 @@ export function create_in_transition(node, fn, params) {
let running = false;
let animation_name;
let task;
let uid = 0;
function cleanup() {
if (animation_name) delete_rule(node, animation_name);
@ -53,11 +54,7 @@ export function create_in_transition(node, fn, params) {
css
} = config;
if (css) {
animation_name = create_rule(0, 1, duration, easing, css);
node.style.animation = (node.style.animation ? ', ' : '') + `${animation_name} ${duration}ms linear ${delay}ms 1 both`;
}
if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);
tick(0, 1);
const start_time = window.performance.now() + delay;
@ -90,6 +87,8 @@ export function create_in_transition(node, fn, params) {
start() {
if (started) return;
delete_rule(node);
if (typeof config === 'function') {
config = config();
wait().then(go);
@ -132,8 +131,7 @@ export function create_out_transition(node, fn, params) {
} = config;
if (css) {
animation_name = create_rule(1, 0, duration, easing, css);
node.style.animation += (node.style.animation ? ', ' : '') + `${animation_name} ${duration}ms linear ${delay}ms 1 both`;
animation_name = create_rule(node, 1, 0, duration, delay, easing, css);
}
const start_time = window.performance.now() + delay;
@ -238,8 +236,7 @@ export function create_bidirectional_transition(node, fn, params, intro) {
// an initial tick and/or apply CSS animation immediately
if (css) {
clear_animation();
animation_name = create_rule(t, b, duration, easing, css);
node.style.animation = (node.style.animation ? `${node.style.animation}, ` : '') + `${animation_name} ${duration}ms linear ${delay}ms 1 both`;
animation_name = create_rule(node, t, b, duration, delay, easing, css);
}
if (b) tick(0, 1);
@ -256,9 +253,7 @@ export function create_bidirectional_transition(node, fn, params, intro) {
if (css) {
clear_animation();
animation_name = create_rule(t, running_program.b, running_program.duration, easing, config.css);
node.style.animation = (node.style.animation ? ', ' : '') + `${animation_name} ${running_program.duration}ms linear 1 forwards`;
animation_name = create_rule(node, t, running_program.b, running_program.duration, 0, easing, config.css);
}
}

@ -0,0 +1,20 @@
export default {
test({ assert, component, target, window, raf }) {
component.visible = true;
const div = target.querySelector('div');
assert.equal(div.style.animation, `__svelte_3809512021_0 100ms linear 0ms 1 both`);
raf.tick(50);
component.visible = false;
// both in and out styles
assert.equal(div.style.animation, `__svelte_3809512021_0 100ms linear 0ms 1 both, __svelte_3750847757_0 100ms linear 0ms 1 both`);
raf.tick(75);
component.visible = true;
// reset original styles
assert.equal(div.style.animation, `__svelte_3809512021_1 100ms linear 0ms 1 both`);
},
};

@ -0,0 +1,25 @@
<script>
export let visible;
function foo() {
return {
duration: 100,
css: t => {
return `opacity: ${t}`;
}
};
}
function bar() {
return {
duration: 100,
css: t => {
return `opacity: ${t}`;
}
};
}
</script>
{#if visible}
<div in:foo out:bar></div>
{/if}
Loading…
Cancel
Save