npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vises/transition

v1.0.0

Published

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

Readme

解决的问题

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