0.1.0 • Published 12 months ago

@nam-hai/water-flow v0.1.0

Weekly downloads
-
License
ISC
Repository
github
Last release
12 months ago

npm version

Introduction

Waterflow is a Nuxt3 library that enables flawless page transitions (Vue3's router too).

QUICK START

$ npm i @nam-hai/water-flow

Setup

Waterflow and its <BufferPage /> hijack <router-view> and can be placed as a replacement (<slot /> in layout.vue for Nuxt3)

<template>
  <BufferPage />
</template>

<script lang='ts'>
import { BufferPage } from '@nam-hai/water-flow';
</script>

App.vue

import index from '@/pages/index.vue';
import about from '@/pages/about.vue';
import home from '@/pages/home.vue';
import { FlowProvider, provideFlowProvider } from '@nam-hai/waterflow'

// provide useFlowProvider through out your whole project
const flowProvider = new FlowProvider()
provideFlowProvider(flowProvider)

// register each page where you will use 
flowProvider.registerPage('index', index)
flowProvider.registerPage('home', home)
flowProvider.registerPage('about', about)

Example

Now use usePageFlow for the page transitions :

usePageFlow({
  props: {
    buttonRef,
    wrapperRef
  },
  // enable crossfade animations and set if the BufferPage is on top or under the current page
  enableCrossfade: 'TOP',
  flowOut: ({ }, resolve) => {
    // insert animation out for the current page
  },
  flowInCrossfade: ({ buttonRef }, resolve) => {
    // insert animation of the next page

    // use the animation engine you like
    const tl = anime.timeline({
        easing: 'easeOutExpo',
        duration: 750
    });

    tl
    .add({
        targets: wrapperRef.value,
        translateX: 250,
    })
    .add({
        targets: buttonRef.value,
        translateX: 250,
        complete: function(anim) {

            // make sure to call the resolve callback to trigger the route change once the animation is over
            resolve()
        }
    }, '+=600') 
  },
})

usePageFlow props

NameTypeDefaultDescription
propsTPass props (Vue Refs) the way you want
enableCrossfadeboolean or 'TOP' or 'BOTTOM'falseEnable crossfade animations and set if the BufferPage is on top or under the current page. True and 'BOTTOM' are the same
flowOutMapMap<string, FlowFunction\>undefinedSpecify a Map of animations for the current page (see more)
flowOutFlowFunction\undefinedSpecify a default animation for the current page
flowInCrossfadeMapMap<string, FlowFunction\>undefinedSpecify a Map of animations for the next page (see more)
flowOutFlowFunction\undefinedSpecify a default animation for the next page
disablePointerEventbooleantrueDisable pointer events for the duration of the animation. Still experimental, clicking on a link during the animation can break app

Type FlowFunction

type FlowFunction<T> = (props: T, resolve: () => void, flowProps?: FlowProps) => void

Function of type FlowFunction have the responsibility to trigger the resolve callback and can be used to animate your pages. Those functions are called in usePageFlow when the route change, ie: onBeforeRouteLeave(to, from, next) and resolve leads to trigger the next callback. props are the Refs you want the access during the animations. They are the ones passed to usePageFlow.

flowProps are props not tied to one specific page. Can be useful for animations on layout elements or canvas. type FlowProps = Record<string, any>

You can add flowProps anywhere in the app :

const webglScene = new WebGLScene()
const flowProvider = useFlowProvider()
flowProvider.addProps('canvas', webglScene)

flowOutMap and flowInCrossfadeMap

You can setup multiple animations to leave one page to another. To do so, you need to pass "FlowMaps". They map from a key to a FlowFunction with the key following the naming convention : routeNameFrom => routeNameTo

index.flow.ts

const transitionIndexOutAbout = ({wrapperRef, buttonRef}, resolve, {canvas}) => {
  // insert your animations
}
const transitionIndexOutHome = ({wrapperRef, buttonRef}, resolve, {canvas}) => {
  // insert your animations
}
const transitionIndexOutDefault = ({wrapperRef, buttonRef}, resolve, {canvas}) => {
  // insert your animations
}

const IndexFlowOutMap = new Map([
  ['index => about', transitionIndexOutAbout],
  ['index => home', transitionIndexOutHome]
  ['default', transitionIndexOutDefault]
])

onFlow

You might want to init things or start some animation after crossfade animations have ended. onMounted will trigger when the crossfade animation start. Use onFlow the same way you'd use onMounted to trigger callback when the page is officially changed and crossfade animations have ended.

Connect your smooth scroll

Waterflow reset the scroll after each page transitions. But if you use a smooth scroll, like Lenis or Locomotive Scroll, this might create conflict. To prevent this, you can connect your smooth scroll to FlowProvider.

Example for Lenis

const flowProvider = useFlowProvider()

useRaf((e) => {
  !flowProvider.flowIsHijacked.value && lenis.raf(e.elapsed)
})

flowProvider.registerScrollInterface({
  resume: () => { lenis.start() },
  stop: () => { lenis.stop() },
  scrollToTop: () => { lenis.scrollTo('top', { immediate: true }) }
})

flowIsHijacked.value is true while the crossfade animations.

0.0.20

1 year ago

0.0.21

1 year ago

0.0.22

1 year ago

0.0.23

12 months ago

0.0.16

1 year ago

0.0.17

1 year ago

0.0.18

1 year ago

0.0.19

1 year ago

0.1.0

12 months ago

0.0.15

1 year ago

0.0.14

1 year ago

0.0.13

1 year ago

0.0.12

1 year ago

0.0.11

1 year ago

0.0.10

1 year ago

0.0.9

1 year ago

0.0.9-1

1 year ago

0.0.9-0

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago