From 27e5331a98e152af8ddaae25f9d497437d792fe1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 13 May 2018 17:45:52 -0400 Subject: [PATCH] css animations --- src/shared/keyed-each.js | 28 ++++++++- test/runtime/samples/animation-css/_config.js | 62 +++++++++++++++++++ test/runtime/samples/animation-css/main.html | 19 ++++++ .../{animation => animation-js}/_config.js | 0 .../{animation => animation-js}/main.html | 0 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 test/runtime/samples/animation-css/_config.js create mode 100644 test/runtime/samples/animation-css/main.html rename test/runtime/samples/{animation => animation-js}/_config.js (100%) rename test/runtime/samples/{animation => animation-js}/main.html (100%) diff --git a/src/shared/keyed-each.js b/src/shared/keyed-each.js index df6023c3e9..b553833bbf 100644 --- a/src/shared/keyed-each.js +++ b/src/shared/keyed-each.js @@ -1,4 +1,4 @@ -import { transitionManager, linear } from './transitions'; +import { transitionManager, linear, generateRule, hash } from './transitions'; export function destroyBlock(block, lookup) { block.d(1); @@ -113,8 +113,10 @@ export function animate(blocks, rects, fn, params) { const from = rects[block.key]; if (!from) continue; - const to = block.node.getBoundingClientRect(); + + if (from.left === to.left && from.right === to.right && from.top === to.top && from.bottom === to.bottom) continue; + const info = fn(block.node, { from, to }, params); const duration = 'duration' in info ? info.duration : 300; @@ -138,6 +140,21 @@ export function animate(blocks, rects, fn, params) { program: delay ? null : program, running: !delay, + start() { + if (info.css) { + const rule = generateRule(program, ease, info.css); + program.name = `__svelte_${hash(rule)}`; + + transitionManager.addRule(rule, program.name); + + block.node.style.animation = (block.node.style.animation || '') + .split(', ') + .filter(anim => anim && (program.delta < 0 || !/__svelte/.test(anim))) + .concat(`${program.name} ${program.duration}ms linear 1 forwards`) + .join(', '); + } + }, + update: now => { const p = now - program.start; const t = program.a + program.delta * ease(p / program.duration); @@ -145,7 +162,10 @@ export function animate(blocks, rects, fn, params) { }, done() { - // TODO remove styles + if (info.css) { + transitionManager.deleteRule(block.node, program.name); + } + animation.running = false; } }; @@ -153,5 +173,7 @@ export function animate(blocks, rects, fn, params) { transitionManager.add(animation); if (info.tick) info.tick(0, 1); + + if (!delay) animation.start(); } } \ No newline at end of file diff --git a/test/runtime/samples/animation-css/_config.js b/test/runtime/samples/animation-css/_config.js new file mode 100644 index 0000000000..3d51582cf7 --- /dev/null +++ b/test/runtime/samples/animation-css/_config.js @@ -0,0 +1,62 @@ +export default { + data: { + things: [ + { id: 1, name: 'a' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 5, name: 'e' } + ] + }, + + html: ` +
a
+
b
+
c
+
d
+
e
+ `, + + test(assert, component, target, window, raf) { + let divs = document.querySelectorAll('div'); + divs.forEach(div => { + div.getBoundingClientRect = function() { + const index = [...this.parentNode.children].indexOf(this); + const top = index * 30; + + return { + left: 0, + right: 100, + top, + bottom: top + 20 + } + }; + }) + + const bcr1 = divs[0].getBoundingClientRect(); + const bcr2 = divs[4].getBoundingClientRect(); + + component.set({ + things: [ + { id: 5, name: 'e' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 1, name: 'a' } + ] + }); + + divs = document.querySelectorAll('div'); + assert.ok(~divs[0].style.animation.indexOf('__svelte')); + assert.equal(divs[1].style.animation, undefined); + assert.equal(divs[2].style.animation, undefined); + assert.equal(divs[3].style.animation, undefined); + assert.ok(~divs[4].style.animation.indexOf('__svelte')); + + raf.tick(100); + assert.deepEqual([ + divs[0].style.animation, + divs[4].style.animation + ], ['', '']); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/animation-css/main.html b/test/runtime/samples/animation-css/main.html new file mode 100644 index 0000000000..1b4b015d1f --- /dev/null +++ b/test/runtime/samples/animation-css/main.html @@ -0,0 +1,19 @@ +{#each things as thing (thing.id)} +
{thing.name}
+{/each} + + \ No newline at end of file diff --git a/test/runtime/samples/animation/_config.js b/test/runtime/samples/animation-js/_config.js similarity index 100% rename from test/runtime/samples/animation/_config.js rename to test/runtime/samples/animation-js/_config.js diff --git a/test/runtime/samples/animation/main.html b/test/runtime/samples/animation-js/main.html similarity index 100% rename from test/runtime/samples/animation/main.html rename to test/runtime/samples/animation-js/main.html