diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte index 1c719c6043..e869816730 100644 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte +++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte @@ -3,6 +3,8 @@ import { crossfade } from 'svelte/transition'; const [send, receive] = crossfade({ + duration: d => Math.sqrt(d * 200), + fallback(node, params) { const style = getComputedStyle(node); const transform = style.transform === 'none' ? '' : style.transform; @@ -18,17 +20,17 @@ } }); + let uid = 1; + let todos = [ - { id: 1, done: false, description: 'write some docs' }, - { id: 2, done: false, description: 'start writing JSConf talk' }, - { id: 3, done: true, description: 'buy some milk' }, - { id: 4, done: false, description: 'mow the lawn' }, - { id: 5, done: false, description: 'feed the turtle' }, - { id: 6, done: false, description: 'fix some bugs' }, + { id: uid++, done: false, description: 'write some docs' }, + { id: uid++, done: false, description: 'start writing blog post' }, + { id: uid++, done: true, description: 'buy some milk' }, + { id: uid++, done: false, description: 'mow the lawn' }, + { id: uid++, done: false, description: 'feed the turtle' }, + { id: uid++, done: false, description: 'fix some bugs' }, ]; - let uid = todos.length + 1; - function add(input) { const todo = { id: uid++, @@ -44,13 +46,42 @@ todos = todos.filter(t => t !== todo); } - function handleKeydown(event) { - if (event.which === 13) { - add(event.target); - } + function mark(todo, done) { + todo.done = done; + remove(todo); + todos = todos.concat(todo); } +
+ e.which === 13 && add(e.target)} + > + +
+

todo

+ {#each todos.filter(t => !t.done) as todo (todo.id)} + + {/each} +
+ +
+

done

+ {#each todos.filter(t => t.done) as todo (todo.id)} + + {/each} +
+
+ - -
- - -
-

todo

- {#each todos.filter(t => !t.done) as todo (todo.id)} - - {/each} -
- -
-

done

- {#each todos.filter(t => t.done) as todo (todo.id)} - - {/each} -
-
\ No newline at end of file + \ No newline at end of file diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/crossfade.js b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/crossfade.js deleted file mode 100644 index e11e18b60e..0000000000 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/crossfade.js +++ /dev/null @@ -1,65 +0,0 @@ -import { quintOut } from 'svelte/easing'; - -export default function crossfade({ send, receive, fallback }) { - let requested = new Map(); - let provided = new Map(); - - function crossfade(from, node) { - const to = node.getBoundingClientRect(); - const dx = from.left - to.left; - const dy = from.top - to.top; - - const style = getComputedStyle(node); - const transform = style.transform === 'none' ? '' : style.transform; - - return { - duration: 400, - easing: quintOut, - css: (t, u) => ` - opacity: ${t}; - transform: ${transform} translate(${u * dx}px,${u * dy}px); - ` - }; - } - - return { - send(node, params) { - provided.set(params.key, { - rect: node.getBoundingClientRect() - }); - - return () => { - if (requested.has(params.key)) { - const { rect } = requested.get(params.key); - requested.delete(params.key); - - return crossfade(rect, node); - } - - // if the node is disappearing altogether - // (i.e. wasn't claimed by the other list) - // then we need to supply an outro - provided.delete(params.key); - return fallback(node, params); - }; - }, - - receive(node, params) { - requested.set(params.key, { - rect: node.getBoundingClientRect() - }); - - return () => { - if (provided.has(params.key)) { - const { rect } = provided.get(params.key); - provided.delete(params.key); - - return crossfade(rect, node); - } - - requested.delete(params.key); - return fallback(node, params); - }; - } - }; -} \ No newline at end of file diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte index c46096c204..3cb21a8ed9 100644 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte +++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte @@ -1,8 +1,10 @@ - - -
- - -
-

todo

- {#each todos.filter(t => !t.done) as todo (todo.id)} - - {/each} -
- -
-

done

- {#each todos.filter(t => t.done) as todo (todo.id)} - - {/each} -
-
\ No newline at end of file + \ No newline at end of file diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/crossfade.js b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/crossfade.js deleted file mode 100644 index e11e18b60e..0000000000 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/crossfade.js +++ /dev/null @@ -1,65 +0,0 @@ -import { quintOut } from 'svelte/easing'; - -export default function crossfade({ send, receive, fallback }) { - let requested = new Map(); - let provided = new Map(); - - function crossfade(from, node) { - const to = node.getBoundingClientRect(); - const dx = from.left - to.left; - const dy = from.top - to.top; - - const style = getComputedStyle(node); - const transform = style.transform === 'none' ? '' : style.transform; - - return { - duration: 400, - easing: quintOut, - css: (t, u) => ` - opacity: ${t}; - transform: ${transform} translate(${u * dx}px,${u * dy}px); - ` - }; - } - - return { - send(node, params) { - provided.set(params.key, { - rect: node.getBoundingClientRect() - }); - - return () => { - if (requested.has(params.key)) { - const { rect } = requested.get(params.key); - requested.delete(params.key); - - return crossfade(rect, node); - } - - // if the node is disappearing altogether - // (i.e. wasn't claimed by the other list) - // then we need to supply an outro - provided.delete(params.key); - return fallback(node, params); - }; - }, - - receive(node, params) { - requested.set(params.key, { - rect: node.getBoundingClientRect() - }); - - return () => { - if (provided.has(params.key)) { - const { rect } = provided.get(params.key); - provided.delete(params.key); - - return crossfade(rect, node); - } - - requested.delete(params.key); - return fallback(node, params); - }; - } - }; -} \ No newline at end of file diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/text.md b/site/content/tutorial/10-transitions/08-deferred-transitions/text.md index e649762f57..49f626554d 100644 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/text.md +++ b/site/content/tutorial/10-transitions/08-deferred-transitions/text.md @@ -4,4 +4,27 @@ title: Deferred transitions A particularly powerful feature of Svelte's transition engine is the ability to *defer* transitions, so that they can be coordinated between multiple elements. -TODO https://github.com/sveltejs/svelte/issues/2159 \ No newline at end of file +Take this pair of todo lists, in which toggling a todo sends it to the opposite list. In the real world, objects don't behave like that — instead of disappearing and reappearing in another place, they move through a series of intermediate positions. Using motion can go a long way towards helping users understand what's happening in your app. + +We can achieve this effect using the `crossfade` function, which creates a pair of transitions called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used. + +Find the `