Skip to content

Commit 3b6485e

Browse files
fix: Make decay easing respect the config.precision prop (#1897)
Co-authored-by: Josh <[email protected]>
1 parent 0362ed1 commit 3b6485e

File tree

3 files changed

+65
-11
lines changed

3 files changed

+65
-11
lines changed

docs/src/pages/common/configs.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ And we've added the following properties `frequency`, `damping`, `round`, `bounc
2929
| tension | 170 | spring energetic load |
3030
| friction | 26 | spring resistence |
3131
| clamp | false | when true, stops the spring once it overshoots its boundaries |
32-
| precision | 0.01 | how close to the end result the animated value gets before we consider it to be "there", this is important with spring animations |
32+
| precision | 0.01 | how close to the end result the animated value gets before we consider it to be "there", this is important with spring and decay animations |
3333
| velocity | 0 | initial velocity (see [v9 changelog](/changelog#changes-in-configvelocity) for a breaking change). |
3434
| easing | t => t | linear by default, you can use any easing you want, for instance d3-ease, we have included a variety of easings see [here](#easings) |
3535
| damping | 1 | The damping ratio, which dictates how the spring slows down. Only works when `frequency` is defined. Defaults to `1`. |

packages/core/src/SpringValue.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,60 @@ function describeConfigProp() {
467467
expect(global.countBounces(spring)).toBeGreaterThan(0)
468468
})
469469
})
470+
describe('the "precision" prop', () => {
471+
describe('stops spring easing when step difference is less than precision', () => {
472+
it.each([100, 10, 1, 0.1, 0.01, 0.001, 0.0001])(
473+
'with precision: %d',
474+
async precision => {
475+
const spring = new SpringValue(0)
476+
477+
spring.start(precision * 10, {
478+
config: {
479+
precision,
480+
},
481+
})
482+
483+
await global.advanceUntilIdle()
484+
const frames = global.getFrames(spring)
485+
486+
expect(spring.get() - frames[frames.length - 2]).toBeGreaterThan(
487+
precision
488+
)
489+
490+
expect(
491+
spring.get() - frames[frames.length - 1]
492+
).toBeLessThanOrEqual(precision)
493+
}
494+
)
495+
})
496+
describe('stops decay easing when step difference is less than precision', () => {
497+
it.each([100, 10, 1, 0.1, 0.01, 0.001, 0.0001])(
498+
'with precision: %d',
499+
async precision => {
500+
const spring = new SpringValue(0)
501+
502+
spring.start({
503+
config: {
504+
velocity: precision * 10,
505+
decay: true,
506+
precision,
507+
},
508+
})
509+
510+
await global.advanceUntilIdle()
511+
const frames = global.getFrames(spring)
512+
513+
expect(
514+
frames[frames.length - 1] - frames[frames.length - 3]
515+
).toBeGreaterThan(precision)
516+
517+
expect(
518+
frames[frames.length - 1] - frames[frames.length - 2]
519+
).toBeLessThanOrEqual(precision)
520+
}
521+
)
522+
})
523+
})
470524
})
471525
}
472526

packages/core/src/SpringValue.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,15 @@ export class SpringValue<T = any> extends FrameValue<T> {
216216

217217
let velocity: number
218218

219+
/** The smallest distance from a value before being treated like said value. */
220+
/**
221+
* TODO: make this value ~0.0001 by default in next breaking change
222+
* for more info see – https://github.com/pmndrs/react-spring/issues/1389
223+
*/
224+
const precision =
225+
config.precision ||
226+
(from == to ? 0.005 : Math.min(1, Math.abs(to - from) * 0.001))
227+
219228
// Duration easing
220229
if (!is.und(config.duration)) {
221230
let p = 1
@@ -259,7 +268,7 @@ export class SpringValue<T = any> extends FrameValue<T> {
259268
const e = Math.exp(-(1 - decay) * elapsed)
260269

261270
position = from + (v0 / (1 - decay)) * (1 - e)
262-
finished = Math.abs(node.lastPosition - position) < 0.1
271+
finished = Math.abs(node.lastPosition - position) <= precision
263272

264273
// derivative of position
265274
velocity = v0 * e
@@ -269,15 +278,6 @@ export class SpringValue<T = any> extends FrameValue<T> {
269278
else {
270279
velocity = node.lastVelocity == null ? v0 : node.lastVelocity
271280

272-
/** The smallest distance from a value before being treated like said value. */
273-
/**
274-
* TODO: make this value ~0.0001 by default in next breaking change
275-
* for more info see – https://github.com/pmndrs/react-spring/issues/1389
276-
*/
277-
const precision =
278-
config.precision ||
279-
(from == to ? 0.005 : Math.min(1, Math.abs(to - from) * 0.001))
280-
281281
/** The velocity at which movement is essentially none */
282282
const restVelocity = config.restVelocity || precision / 10
283283

0 commit comments

Comments
 (0)