Skip to content

Commit

Permalink
refactor(useTransition): cleaning up (#385)
Browse files Browse the repository at this point in the history
  • Loading branch information
scottbedard committed Mar 18, 2021
1 parent d57c3cc commit f4a302b
Show file tree
Hide file tree
Showing 6 changed files with 297 additions and 294 deletions.
2 changes: 1 addition & 1 deletion packages/core/useTransition/demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const toggle = () => {
}
.vector.track .relative {
padding-bottom: 56.25%;
padding-bottom: 30%;
}
.vector.track .sled {
Expand Down
43 changes: 31 additions & 12 deletions packages/core/useTransition/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,49 @@ Transition between values

## Usage

For simple transitions, provide a numeric source value. When this changes, a new transition will begin. If the source changes while a transition is in progress, a new transition will begin from where the previous one was interrupted.

```js
import { useTransition, TransitionPresets } from '@vueuse/core'
import { ref } from 'vue'
import { useTransition } from '@vueuse/core'

useTransition(source, {
const source = ref(0)

const output = useTransition(source, {
duration: 1000,
transition: TransitionPresets.easeInOutCubic,
})
```

The following transitions are available via the `TransitionPresets` constant.
To synchronize transitions, use an array of values. To demonstrate this, here we'll transition between color values.

```js
const source = ref([0, 0, 0])

const output = useTransition(source)

const color = computed(() => {
const [r, g, b] = output.value
return `rgb(${r}, ${g}, ${b})`
})
```

Transition easing can be customized using cubic bezier curves. Transitions defined this way work the same as [CSS easing functions](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#easing_functions).

```js
useTransition(source, {
transition: [0.75, 0, 0.25, 1],
})
```

The following common transitions are available via the `TransitionPresets` constant.

- [`linear`](https://cubic-bezier.com/#0,0,1,1)
- [`easeInSine`](https://cubic-bezier.com/#.12,0,.39,0)
- [`easeOutSine`](https://cubic-bezier.com/#.61,1,.88,1)
- [`easeInOutSine`](https://cubic-bezier.com/#.37,0,.63,1)
- [`easeInQuad`](https://cubic-bezier.com/#.11,0,.5,0)
- [`easeOutQuad`](https://cubic-bezier.com/#.5,1,.89,1)
- [`easeInOutQuad`](https://cubic-bezier.com/#.45,0,.55,1)
- [`easeInCubic`](https://cubic-bezier.com/#.32,0,.67,0)
- [`easeOutCubic`](https://cubic-bezier.com/#.33,1,.68,1)
- [`easeInOutCubic`](https://cubic-bezier.com/#.65,0,.35,1)
Expand All @@ -43,14 +70,6 @@ The following transitions are available via the `TransitionPresets` constant.
- [`easeOutBack`](https://cubic-bezier.com/#.34,1.56,.64,1)
- [`easeInOutBack`](https://cubic-bezier.com/#.68,-.6,.32,1.6)

Custom transitions can be defined using cubic bezier curves. Transitions defined this way work the same as [CSS easing functions](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function).

```js
useTransition(source, {
transition: [0.75, 0, 0.25, 1],
})
```

For more complex transitions, a custom function can be provided.

```js
Expand Down
170 changes: 170 additions & 0 deletions packages/core/useTransition/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { promiseTimeout } from '@vueuse/shared'
import { ref } from 'vue-demi'
import { useTransition } from '.'

const expectBetween = (val: number, floor: number, ceiling: number) => {
expect(val).toBeGreaterThan(floor)
expect(val).toBeLessThan(ceiling)
}

describe('useTransition', () => {
it('transitions between numbers', async() => {
const source = ref(0)
const transition = useTransition(source, { duration: 100 })

expect(transition.value).toBe(0)

source.value = 1

await promiseTimeout(50)
expectBetween(transition.value, 0, 1)

await promiseTimeout(100)
expect(transition.value).toBe(1)
})

it('transitions between vectors', async() => {
const source = ref([0, 0])
const transition = useTransition(source, { duration: 100 })

expect(transition.value).toEqual([0, 0])

source.value = [1, 1]

await promiseTimeout(50)
expectBetween(transition.value[0], 0, 1)
expectBetween(transition.value[1], 0, 1)

await promiseTimeout(100)
expect(transition.value[0]).toBe(1)
expect(transition.value[1]).toBe(1)
})

it('supports cubic bezier curves', async() => {
const source = ref(0)

// https://cubic-bezier.com/#0,2,0,1
const easeOutBack = useTransition(source, {
duration: 100,
transition: [0, 2, 0, 1],
})

// https://cubic-bezier.com/#1,0,1,-1
const easeInBack = useTransition(source, {
duration: 100,
transition: [1, 0, 1, -1],
})

source.value = 1

await promiseTimeout(50)
expectBetween(easeOutBack.value, 1, 2)
expectBetween(easeInBack.value, -1, 0)

await promiseTimeout(100)
expect(easeOutBack.value).toBe(1)
expect(easeInBack.value).toBe(1)
})

it('supports custom easing functions', async() => {
const source = ref(0)
const linear = jest.fn(n => n)
const transition = useTransition(source, {
duration: 100,
transition: linear,
})

expect(linear).not.toHaveBeenCalled()

source.value = 1

await promiseTimeout(50)
expect(linear).toHaveBeenCalled()
expectBetween(transition.value, 0, 1)

await promiseTimeout(100)
expect(transition.value).toBe(1)
})

it('supports dynamic transitions', async() => {
const source = ref(0)
const first = jest.fn(n => n)
const second = jest.fn(n => n)
const easingFn = ref(first)

useTransition(source, {
duration: 100,
transition: easingFn,
})

expect(first).not.toHaveBeenCalled()
expect(second).not.toHaveBeenCalled()

source.value = 1

await promiseTimeout(50)
expect(first).toHaveBeenCalled()
expect(second).not.toHaveBeenCalled()

first.mockReset()
second.mockReset()

easingFn.value = second
source.value = 2

await promiseTimeout(100)
expect(first).not.toHaveBeenCalled()
expect(second).toHaveBeenCalled()
})

it('supports dynamic durations', async() => {
const source = ref(0)
const duration = ref(100)
const transition = useTransition(source, { duration })

source.value = 1

await promiseTimeout(50)
expectBetween(transition.value, 0, 1)

await promiseTimeout(100)
expect(transition.value).toBe(1)

duration.value = 200
source.value = 2

await promiseTimeout(150)
expectBetween(transition.value, 1, 2)

await promiseTimeout(100)
expect(transition.value).toBe(2)
})

it('fires onStarted and onFinished callbacks', async() => {
const source = ref(0)
const onStarted = jest.fn()
const onFinished = jest.fn()

useTransition(source, {
duration: 100,
onStarted,
onFinished,
})

expect(onStarted).not.toHaveBeenCalled()
expect(onFinished).not.toHaveBeenCalled()

source.value = 1

await promiseTimeout(50)
expect(onStarted).toHaveBeenCalled()
expect(onFinished).not.toHaveBeenCalled()

onStarted.mockReset()
onFinished.mockReset()

await promiseTimeout(100)
expect(onStarted).not.toHaveBeenCalled()
expect(onFinished).toHaveBeenCalled()
})
})

0 comments on commit f4a302b

Please sign in to comment.