@vises/transition

1.0.0 • Public • Published

解决的问题

1.动画未完成页面数字滚动,图表开始渲染 2.统一管理页面进场,出场. 3.出场动画时间不一样

TransitionWrap

TransitionPage的容器. TransitionWrap会获取子孙TransitionPage组件,value值等于TransitionPage的keys时渲染页面

属性 说明 类型 默认
value 渲染哪一个transitionPage页面 string -
inEndFn 整个页面进场动画结束回调 Function -
outEndFn 整个页面出场动画结束回调 Function -

TransitionPage

页面容器

属性 说明 类型 默认
page 页面dom dom -
keys 页面标识 string -

Transition

在show改变时会给Transition添加不同的类名

属性 说明 类型 默认
name 类名前缀 string default
className 类名 class -
style 样式 css -
inEndFn 进场动画结束回调函数 Function -
outEndFn 出场动画结束回调函数 Function -

过渡的类名

1.[name]-in: 在元素被插入之时生效,在元素被插入之后的下一帧移除。 2.[name]-in-active: 在元素被插入时生效 3.[name]-out-to: 在show改为false生效 4.[name]-out-active: 在show改为false生效

示例

项目入口文件 page/index.tsx

import { useState } from 'react';
import { TransitionWrap, TransitionPage } from '@/components/transition'; // 引入组件容器
import PageA from './PageA';
import PageB from './PageB';

const IndexPage = () => {
  const [pageName, setPageName] = useState('PageA'); // 当前页面

  // 出场动画结束回调
  let handlePage = () => {
    console.log('出场动画结束回调')
  };
  
  // 接收到中控发来消息
  const API_PageChange = (data: any) => {
    setPageName(data.page)
  }

  return (
    <TransitionWrap value={pageName} outEndFn={handlePage}>
      <button onClick={() => API_PageChange({ page: 'PageA' })}>切换到: PageA</button>
      <button onClick={() => API_PageChange({ page: 'PageB' })}>切换到: PageB</button>
      <TransitionPage keys="PageA" page={<PageA />} />
      <TransitionPage keys="PageB" page={<PageB />} />
    </TransitionWrap>
  );
}

export default IndexPage;

pageA页面中

import styles from './index.less';
import { Transition, TransitionWrap, TransitionPage } from '@/components/transition'; // 引入过渡组件
import CountUp from '@/components/CountUp';
import { useState } from 'react';


const pageA = () => {
  const [pageName, setPageName] = useState('right1'); // 当前页面

  // 接收到中控发来消息
  const API_PageChange = (data: any) => {
    setPageName(data.page)
  }

  return <div>
      <button onClick={() => API_PageChange({ page: 'right1' })}>切换到: right1</button>
      <button onClick={() => API_PageChange({ page: 'right2' })}>切换到: right2</button>
      

    
      <div className={styles.page}>

      <Transition name="left" className={styles.left} inEndFn={() => {console.log('进场动画结束')}}>
        name 为 left
        

        <CountUp end={100} />
      </Transition>

      <Transition name="center">
        <h1>PageA</h1>
        <h1>name 为 center</h1>
      </Transition>

      <TransitionWrap value={pageName}>
        <TransitionPage keys="right1" page={
          <Transition name="right" className={styles.right}>
            name 为 right1
            

            page 为 1
            

            <CountUp end={100} />
          </Transition>
        } />
        <TransitionPage keys="right2" page={
          <Transition name="right" className={styles.right}>
            name 为 right
            

            page 为 2
            

            <CountUp end={200} />
          </Transition>
        } />
      </TransitionWrap>
    </div>
  </div>
}

export default pageA;

// ---------------------styles---------------------
.page {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 40px;
  box-sizing: border-box;
  .left {
    box-sizing: border-box;
    width: 200px;
    height: 400px;
    background-color: #f00;
  }
  .right {
    box-sizing: border-box;
    width: 200px;
    height: 400px;
    background-color: #f0f;
  }
}

pageB页面中

import styles from './index.less';
import { Transition } from '@/components/transition'; // 引入过渡组件
import CountUp from '@/components/CountUp';


const pageB = () => {
  return <div className={styles.page}>
    <Transition name="left2" className={styles.left} inEndFn={() => {console.log('进场动画结束')}}>
      name 为 left2
      

      <CountUp end={100} />
    </Transition>

    <Transition name="center2">
      <h1>PageB</h1>
      <h1>name 为 center2</h1>
    </Transition>
    
    <Transition name="right2" className={styles.right}>
      name 为 right2
    </Transition>
  </div>
}

export default pageB;

// ---------------------styles---------------------
  .page {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 40px;
    box-sizing: border-box;
    .left {
      box-sizing: border-box;
      width: 200px;
      height: 400px;
      background-color: #f00;
    }
    .right {
      box-sizing: border-box;
      width: 200px;
      height: 400px;
      background-color: #f0f;
    }
  }

此时的Transition的css为:

.left-in, .left-out-to {
  transform: translateX(-150%);
}

.left-in-active, .left-out-active {
  transition: transform 1.8s;
}

.right-in, .right-out-to {
  transform: translateX(150%);
}

.right-in-active, .right-out-active {
  transition: transform .8s;
}

.center-in-active {
  animation: centerIn .8s linear;
}

.center-out-active {
  animation: centerOut .8s linear forwards;
}

@keyframes centerIn {
  0% { transform: scale(0) }
  100% { transform: scale(1); }
}

@keyframes centerOut {
  0% { transform: scale(1) }
  100% { transform: scale(0); }
}

.left2-in-active {
  animation: left2In .8s linear;
}

@keyframes left2In {
  0% { 
    transform: translateX(-150%);
    height: 20px;
    overflow: hidden;
  }
  40% { 
    transform: translateX(0%);
    height: 20px;
    overflow: hidden;
  }
  100% { 
    transform: translateX(0%);
    height: 400px;
    overflow: hidden;
  }
}

.left2-out-active {
  animation: left2Out .8s linear;
}

@keyframes left2Out {
  0% { 
    transform: translateX(0%);
    height: 400px;
    overflow: hidden;
  }
  40% { 
    transform: translateX(0%);
    height: 20px;
    overflow: hidden;
  }
  100% { 
    transform: translateX(-150%);
    height: 20px;
    overflow: hidden;
  }
}


.center2-in, .center2-out-to {
  transform: translateY(-250%);
}

.center2-in-active, .center2-out-active {
  transition: transform .8s;
}

.right2-in-active {
  animation: right2In .8s linear;
}

@keyframes right2In {
  0% { 
    opacity: 0;
    border-radius: 100%;
    width: 0;
    height: 0;
    overflow: hidden;
  }
  100% { 
    opacity: 1;
    border-radius: 0%;
    overflow: hidden;
  }
}

.right2-out-active {
  animation: right2Out .8s linear;
}

@keyframes right2Out {
  0% { 
    border-radius: 0%;
    overflow: hidden;
  }
  100% { 
    width: 0;
    height: 0;
    opacity: 0;
    border-radius: 100%;
    overflow: hidden;
  }
}

.left-in, .left-out-to {
  transform: translateX(-110%);
}

.left-in-active, .left-out-active {
  transition: transform .8s;
}

.right-in, .right-out-to {
  transform: translateX(110%);
}

.right-in-active, .right-out-active {
  transition: transform .8s;
}

Transition下的组件获取页面进场结束 如 CountUp 组件

import ReactCountUp from 'react-countup';
import { CountUpProps } from 'react-countup/build/CountUp';
import { useTransitionEnd } from '@/components/transition'; // 页面进场结束use
import { useState } from 'react';
const CountUp: React.FC<CountUpProps> = (props) => {
    const [flag, setFlag] = useState(false);
    useTransitionEnd(() => { setFlag(true); console.log('进场动画结束') });
  return <ReactCountUp  duration={2.75} {...props} end={!flag ? 0 : props.end}></ReactCountUp>;
};

export default CountUp;

demo下载

demo.zip

/@vises/transition/

    Package Sidebar

    Install

    npm i @vises/transition

    Weekly Downloads

    0

    Version

    1.0.0

    License

    ISC

    Unpacked Size

    15.9 kB

    Total Files

    4

    Last publish

    Collaborators

    • latiao2
    • souporchan
    • lstdev
    • cnyballk