Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Make decay easing respect the config.precision prop #1897

Merged
merged 5 commits into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/pages/common/configs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ And we've added the following properties `frequency`, `damping`, `round`, `bounc
| tension | 170 | spring energetic load |
| friction | 26 | spring resistence |
| clamp | false | when true, stops the spring once it overshoots its boundaries |
| 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 |
| 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 |
| velocity | 0 | initial velocity (see [v9 changelog](/changelog#changes-in-configvelocity) for a breaking change). |
| 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) |
| damping | 1 | The damping ratio, which dictates how the spring slows down. Only works when `frequency` is defined. Defaults to `1`. |
Expand Down
54 changes: 54 additions & 0 deletions packages/core/src/SpringValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,60 @@ function describeConfigProp() {
expect(global.countBounces(spring)).toBeGreaterThan(0)
})
})
describe('the "precision" prop', () => {
describe('stops spring easing when step difference is less than precision', () => {
it.each([100, 10, 1, 0.1, 0.01, 0.001, 0.0001])(
'with precision: %d',
async precision => {
const spring = new SpringValue(0)

spring.start(precision * 10, {
config: {
precision,
},
})

await global.advanceUntilIdle()
const frames = global.getFrames(spring)

expect(spring.get() - frames[frames.length - 2]).toBeGreaterThan(
precision
)

expect(
spring.get() - frames[frames.length - 1]
).toBeLessThanOrEqual(precision)
}
)
})
describe('stops decay easing when step difference is less than precision', () => {
it.each([100, 10, 1, 0.1, 0.01, 0.001, 0.0001])(
'with precision: %d',
async precision => {
const spring = new SpringValue(0)

spring.start({
config: {
velocity: precision * 10,
decay: true,
precision,
},
})

await global.advanceUntilIdle()
const frames = global.getFrames(spring)

expect(
frames[frames.length - 1] - frames[frames.length - 3]
).toBeGreaterThan(precision)

expect(
frames[frames.length - 1] - frames[frames.length - 2]
).toBeLessThanOrEqual(precision)
}
)
})
})
})
}

Expand Down
20 changes: 10 additions & 10 deletions packages/core/src/SpringValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,15 @@ export class SpringValue<T = any> extends FrameValue<T> {

let velocity: number

/** The smallest distance from a value before being treated like said value. */
/**
* TODO: make this value ~0.0001 by default in next breaking change
* for more info see – https://github.com/pmndrs/react-spring/issues/1389
*/
const precision =
config.precision ||
(from == to ? 0.005 : Math.min(1, Math.abs(to - from) * 0.001))

// Duration easing
if (!is.und(config.duration)) {
let p = 1
Expand Down Expand Up @@ -259,7 +268,7 @@ export class SpringValue<T = any> extends FrameValue<T> {
const e = Math.exp(-(1 - decay) * elapsed)

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

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

/** The smallest distance from a value before being treated like said value. */
/**
* TODO: make this value ~0.0001 by default in next breaking change
* for more info see – https://github.com/pmndrs/react-spring/issues/1389
*/
const precision =
config.precision ||
(from == to ? 0.005 : Math.min(1, Math.abs(to - from) * 0.001))

/** The velocity at which movement is essentially none */
const restVelocity = config.restVelocity || precision / 10

Expand Down