From 714508ccc549ab5790eefaa59502d173619cf7c8 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 21 Oct 2019 15:33:19 -0400 Subject: [PATCH 1/2] allow spring/tweened values to be initially undefined - closes #3761 --- src/runtime/motion/spring.ts | 4 ++-- src/runtime/motion/tweened.ts | 7 ++++++- test/motion/index.js | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 test/motion/index.js diff --git a/src/runtime/motion/spring.ts b/src/runtime/motion/spring.ts index 7742dd4106..20fa6ffcde 100644 --- a/src/runtime/motion/spring.ts +++ b/src/runtime/motion/spring.ts @@ -65,7 +65,7 @@ interface Spring extends Readable{ stiffness: number; } -export function spring(value: T, opts: SpringOpts = {}): Spring { +export function spring(value?: T, opts: SpringOpts = {}): Spring { const store = writable(value); const { stiffness = 0.15, damping = 0.8, precision = 0.01 } = opts; @@ -84,7 +84,7 @@ export function spring(value: T, opts: SpringOpts = {}): Spring { target_value = new_value; const token = current_token = {}; - if (opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) { + if (value == null || opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) { cancel_task = true; // cancel any running animation last_time = now(); last_value = value; diff --git a/src/runtime/motion/tweened.ts b/src/runtime/motion/tweened.ts index 7159c17eb5..e33f0f79f9 100644 --- a/src/runtime/motion/tweened.ts +++ b/src/runtime/motion/tweened.ts @@ -69,13 +69,18 @@ interface Tweened extends Readable { update(updater: Updater, opts: Options): Promise; } -export function tweened(value: T, defaults: Options = {}): Tweened { +export function tweened(value?: T, defaults: Options = {}): Tweened { const store = writable(value); let task: Task; let target_value = value; function set(new_value: T, opts: Options) { + if (value == null) { + store.set(value = new_value); + return Promise.resolve(); + } + target_value = new_value; let previous_task = task; diff --git a/test/motion/index.js b/test/motion/index.js new file mode 100644 index 0000000000..33489b18e1 --- /dev/null +++ b/test/motion/index.js @@ -0,0 +1,23 @@ +import * as assert from 'assert'; +import { get } from '../../store'; +import { spring, tweened } from '../../motion'; + +describe('motion', () => { + describe('spring', () => { + it('handles initially undefined values', () => { + const size = spring(); + + size.set(100); + assert.equal(get(size), 100); + }); + }); + + describe('tweened', () => { + it('handles initially undefined values', () => { + const size = tweened(); + + size.set(100); + assert.equal(get(size), 100); + }); + }); +}); From e8f5b24143feea5ca348fb2991a05e16e22ec2fc Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Sun, 27 Oct 2019 21:10:12 -0400 Subject: [PATCH 2/2] docs and a fix for #3761 --- site/content/docs/03-run-time.md | 22 ++++++++++++++++++++++ src/runtime/motion/spring.ts | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index 551945eade..997cf10571 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -433,6 +433,19 @@ Out of the box, Svelte will interpolate between two numbers, two arrays or two o --- +If the initial value is `undefined` or `null`, the first value change will take effect immediately. This is useful when you have tweened values that are based on props, and don't want any motion when the component first renders. + +```js +const size = tweened(undefined, { + duration: 300, + easing: cubicOut +}); + +$: $size = big ? 100 : 10; +``` + +--- + The `interpolate` option allows you to tween between *any* arbitrary values. It must be an `(a, b) => t => value` function, where `a` is the starting value, `b` is the target value, `t` is a number between 0 and 1, and `value` is the result. For example, we can use the [d3-interpolate](https://github.com/d3/d3-interpolate) package to smoothly interpolate between two colours. ```html @@ -493,6 +506,15 @@ Both `set` and `update` can take a second argument — an object with `hard` or ``` +--- + +If the initial value is `undefined` or `null`, the first value change will take effect immediately, just as with `tweened` values (see above). + +```js +const size = spring(); +$: $size = big ? 100 : 10; +``` + ### `svelte/transition` The `svelte/transition` module exports six functions: `fade`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with svelte [`transitions`](docs#Transitions). diff --git a/src/runtime/motion/spring.ts b/src/runtime/motion/spring.ts index 20fa6ffcde..1804ff43a5 100644 --- a/src/runtime/motion/spring.ts +++ b/src/runtime/motion/spring.ts @@ -87,9 +87,9 @@ export function spring(value?: T, opts: SpringOpts = {}): Spring { if (value == null || opts.hard || (spring.stiffness >= 1 && spring.damping >= 1)) { cancel_task = true; // cancel any running animation last_time = now(); - last_value = value; + last_value = new_value; store.set(value = target_value); - return new Promise(f => f()); // fulfil immediately + return Promise.resolve(); } else if (opts.soft) { const rate = opts.soft === true ? .5 : +opts.soft; inv_mass_recovery_rate = 1 / (rate * 60);