-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from swup/next
Update for swup 4
- Loading branch information
Showing
8 changed files
with
395 additions
and
1,022 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Changelog | ||
|
||
<!-- ## [Unreleased] --> | ||
|
||
## [3.0.0] - 2023-07-26 | ||
|
||
- Allow returning Promises and async/await animation functions | ||
- Breaking: the first matching rule is used | ||
- Update for swup 4 compatibility | ||
|
||
## [2.0.0] - 2023-03-13 | ||
|
||
- Switch to microbundle | ||
- Export native ESM module | ||
|
||
## [1.0.5] - 2022-08-21 | ||
|
||
- Bail early if no animation found | ||
|
||
## [1.0.4] - 2022-08-15 | ||
|
||
- Remove reference to global swup instance | ||
|
||
## [1.0.3] - 2019-05-23 | ||
|
||
- Improve how animations are ranked | ||
|
||
## [1.0.2] - 2019-05-13 | ||
|
||
- Fix plugin name | ||
|
||
## [1.0.1] - 2019-05-02 | ||
|
||
- Update readme | ||
|
||
## [1.0.0] - 2019-05-02 | ||
|
||
- Initial release | ||
|
||
[Unreleased]: https://github.com/swup/js-plugin/compare/3.0.0...HEAD | ||
|
||
[3.0.0]: https://github.com/swup/js-plugin/releases/tag/3.0.0 | ||
[2.0.0]: https://github.com/swup/js-plugin/releases/tag/2.0.0 | ||
[1.0.5]: https://github.com/swup/js-plugin/releases/tag/1.0.5 | ||
[1.0.4]: https://github.com/swup/js-plugin/releases/tag/1.0.4 | ||
[1.0.3]: https://github.com/swup/js-plugin/releases/tag/1.0.3 | ||
[1.0.2]: https://github.com/swup/js-plugin/releases/tag/1.0.2 | ||
[1.0.1]: https://github.com/swup/js-plugin/releases/tag/1.0.1 | ||
[1.0.0]: https://github.com/swup/js-plugin/releases/tag/1.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
# Swup JS Plugin | ||
|
||
A [swup](https://swup.js.org) plugin for managing animations in JS. | ||
|
||
- Use JavaScript for timing animations instead of CSS | ||
- Successor to the deprecated [swupjs](https://github.com/swup/swupjs) library | ||
|
||
## Installation | ||
|
||
Install the plugin from npm and import it into your bundle. | ||
|
||
```bash | ||
npm install @swup/js-plugin | ||
``` | ||
|
||
```js | ||
import SwupJsPlugin from '@swup/js-plugin'; | ||
``` | ||
|
||
Or include the minified production file from a CDN: | ||
|
||
```html | ||
<script src="https://unpkg.com/@swup/js-plugin@3"></script> | ||
``` | ||
|
||
## Usage | ||
|
||
To run this plugin, include an instance in the swup options. | ||
|
||
```js | ||
const swup = new Swup({ | ||
plugins: [ | ||
new SwupJsPlugin({ animations: [ /* your custom animation functions */ ] }) | ||
] | ||
}); | ||
``` | ||
|
||
## Options | ||
|
||
The plugin expects an `array` of animation objects. | ||
The example below is the default setup and defines two animations, where `out` is the | ||
animation function being executed before the content is being replaced, and `in` is | ||
the animation being executed after the content is replaced: | ||
|
||
```js | ||
{ | ||
animations: [ | ||
{ | ||
from: '(.*)', // matches any route | ||
to: '(.*)', // matches any route | ||
out: done => done(), // immediately continues | ||
in: done => done() // immediately continues | ||
} | ||
] | ||
} | ||
``` | ||
|
||
This is also the fallback animation in case no other matching animations were found. | ||
|
||
Animations are chosen based on the `from` and `to` properties of the object, which are | ||
compared against the current visit (urls of current and next page). | ||
Learn more on [choosing the animation](#choosing-the-animation) below. | ||
|
||
## Animation function | ||
|
||
The animation function is executed for each corresponding animation phase. Inside the animation | ||
function, you manage the animation yourself and signal when it has finished. It receives two | ||
arguments: a `done` function and a `data` object. | ||
|
||
```js | ||
out: (done, data) => { | ||
// Signal the end of the animation by calling done() | ||
// Access info about the animation inside the data argument | ||
} | ||
``` | ||
|
||
### Signaling the end of an animation | ||
|
||
Calling the `done()` function signals to swup that the animation has finished and it can proceed | ||
to the next step: replacing the content or finishing the visit. You can pass along the `done()` | ||
function as a callback to your animation library. The example below will wait for two seconds before replacing the content. | ||
|
||
```js | ||
out: (done) => { | ||
setTimeout(done, 2000); | ||
} | ||
``` | ||
|
||
#### Promises and async/await | ||
|
||
If your animation library returns Promises, you can also return the Promise directly from your | ||
animation function. Swup will consider the animation to be finished when the Promise resolves. | ||
The `done` function is then no longer required. | ||
|
||
```js | ||
out: () => { | ||
return myAnimationLibrary.animate(/* */).then(() => {}); | ||
} | ||
``` | ||
|
||
This also allows `async/await` syntax for convenience. | ||
|
||
```js | ||
out: async () => { | ||
await myAnimationLibrary.animate(/* */); | ||
} | ||
``` | ||
|
||
### Data object | ||
|
||
The second parameter is an object that contains useful data about the animation, such as the visit | ||
object (containing actual before/after routes), the `from` and `to` parameters of the | ||
animation object, and the route params. | ||
|
||
```js | ||
{ | ||
visit: { /* */ }, // swup global visit object | ||
direction: 'in', | ||
from: { | ||
url: '/', | ||
pattern: '(.*)', | ||
params: {} | ||
}, | ||
to: { | ||
url: '/about', | ||
pattern: '(.*)', | ||
params: {} | ||
} | ||
} | ||
``` | ||
|
||
## Examples | ||
|
||
Basic usage examples for a fade transition implemented in popular animation libraries: | ||
|
||
### [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API) | ||
|
||
```js | ||
{ | ||
from: '(.*)', | ||
to: '(.*)', | ||
in: async () => { | ||
const container = document.querySelector('#swup'); | ||
await container.animate([{ opacity: 0 }, { opacity: 1 }], 500).finished; | ||
}, | ||
out: async () => { | ||
const container = document.querySelector('#swup'); | ||
await container.animate([{ opacity: 1 }, { opacity: 0 }], 500).finished; | ||
} | ||
} | ||
``` | ||
|
||
### [GSAP](https://greensock.com/gsap/) | ||
|
||
```js | ||
{ | ||
from: '(.*)', | ||
to: '(.*)', | ||
out: (done) => { | ||
const container = document.querySelector('#swup'); | ||
container.style.opacity = 1; | ||
gsap.to(container, { opacity: 0, duration: 0.5, onComplete: done }); | ||
}, | ||
in: (done) => { | ||
const container = document.querySelector('#swup'); | ||
container.style.opacity = 0; | ||
gsap.to(container, { opacity: 1, duration: 0.5, onComplete: done }); | ||
} | ||
} | ||
``` | ||
|
||
### [anime.js](https://animejs.com/) | ||
|
||
```js | ||
{ | ||
from: '(.*)', | ||
to: '(.*)', | ||
out: (done) => { | ||
const container = document.querySelector('#swup'); | ||
container.style.opacity = 1; | ||
anime({ targets: container, opacity: 0, duration: 500, complete: done }); | ||
}, | ||
in: (done) => { | ||
const container = document.querySelector('#swup'); | ||
container.style.opacity = 0; | ||
anime({ targets: container, opacity: 1, duration: 500, complete: done }); | ||
} | ||
} | ||
``` | ||
|
||
## Choosing the animation | ||
|
||
As mentioned above, the animation is chosen based on the `from` and `to` properties of the animation object. | ||
Those properties can take several forms: | ||
|
||
- a string (matching a route exactly) | ||
- a regular expression | ||
- A route pattern like `/foo/:bar`) parsed by [path-to-regexp](https://github.com/pillarjs/path-to-regexp) | ||
- a custom animation name taken from the `data-swup-animation` attribute of the clicked link | ||
|
||
The most fitting route is always chosen. | ||
Keep in mind, that two routes can be evaluated as "same fit". | ||
In this case, the first one defined in the options is used, so usually you would like to define the more specific routes first. | ||
See the example below for more info. | ||
|
||
```js | ||
[ | ||
// animation 1 | ||
{ from: '/', to: 'custom' }, | ||
// animation 2 | ||
{ from: '/', to: '/post' }, | ||
// animation 3 | ||
{ from: '/', to: '/post/:id' }, | ||
// animation 4 | ||
{ from: '/', to: /pos(.*)/ }, | ||
// animation 5 | ||
{ from: '(.*)', to: '(.*)' }, | ||
]; | ||
``` | ||
|
||
- from `/` to `/post` → animation **2** | ||
- from `/` to `/posting` → animation **4** | ||
- from `/` to `/post/12` → animation **3** | ||
- from `/` to `/some-route` → animation **5** | ||
- from `/` to `/post` with `data-swup-animation="custom"` → animation **1** |
Oops, something went wrong.