Skip to content

创建欢迎页面

还原页面内容

将欢迎界面的代码修改成之前的样子,使用unocss的进行样式绘制,具体代码见链接

添加第一个页面HTML

修改WeclomeLayout.tsx组件,分上中下三部分,中间部分通过动画来滑动,其他部分不做处理,并根据linkMap来映射下一页的跳转。

tsx
import { Link, useLocation, useOutlet, } from 'react-router-dom'
import { animated, useTransition } from 'react-spring'
import type { ReactNode } from 'react'
import { useRef } from 'react'
import logo from '../assets/images/logo.svg'
const linkMap: Record<string, string> = {
  '/welcome/1': '/welcome/2',
  '/welcome/2': '/welcome/3',
  '/welcome/3': '/welcome/4',
  '/welcome/4': '/welcome/xxx',
}
export const WelcomeLayout: React.FC = () => {
  const map = useRef<Record<string, ReactNode>>({})
  const location = useLocation() // 获取当前地址栏的信息
  const outlet = useOutlet()
  map.current[location.pathname] = outlet
  const transitions = useTransition(location.pathname, {
    from: { transform: location.pathname === '/welcome/1' ? 'translateX(0%)' : 'translateX(100%)' },
    enter: { transform: 'translateX(0%)' },
    leave: { transform: 'translateX(-100%)' },
    config: { duration: 300 }
  })
  return (
    <div>
      <header>
        <img src={logo} />
        <h1>山竹记账</h1>
      </header>
      <main>
        {transitions((style, pathname) =>
      <animated.div key={pathname} style={style}>
        {map.current[pathname]}
      </animated.div>
                    )}
      </main>
      <footer>
        <Link to={linkMap[location.pathname]}>下一页</Link>
        <Link to="/welcome/xxx">跳过</Link>
      </footer>
    </div>
  )
}
tsx
export const Welcome1: React.FC = () => {
  return (
    <div text-center>
      <img src={p1} />
      <h2 text-32px mt-48px>
        会挣钱 <br/>
        还要会省钱
      </h2>
    </div>
  )
}

添加第一个页面的样式

底部下一页和跳过使用grid布局进行分布区域,添加样式具体见链接

完成 4 个界面

4个界面内容具体见链接

优化动画的两个细节

  1. 提高流畅度
  2. 解决如果图片加载慢会闪烁的问题

中间部分页面开始动画操作的时候添加相对绝对定位,然后在离开后复位的时候在改为相对定位,提高动画的流畅程度,并将样式添加至<animated.div />style内,详细代码见链接

tsx
import { Link, useLocation, useOutlet, } from 'react-router-dom'
import { animated, useTransition } from 'react-spring'
import type { ReactNode } from 'react'
import { useRef, useState } from 'react'
import logo from '../assets/images/logo.svg'
const linkMap: Record<string, string> = {
  '/welcome/1': '/welcome/2',
  '/welcome/2': '/welcome/3',
  '/welcome/3': '/welcome/4',
  '/welcome/4': '/welcome/xxx',
}
export const WelcomeLayout: React.FC = () => {
  const map = useRef<Record<string, ReactNode>>({})
  const location = useLocation() // 获取当前地址栏的信息
  const outlet = useOutlet()
  map.current[location.pathname] = outlet
  const [extraStyle, setExtraStyle] = useState({ position: 'relative' })
  const transitions = useTransition(location.pathname, {
    from: { transform: location.pathname === '/welcome/1' ? 'translateX(0%)' : 'translateX(100%)' },
    enter: { transform: 'translateX(0%)' },
    leave: { transform: 'translateX(-100%)' },
    config: { duration: 300 },
    onStart: () => {
      setExtraStyle({ position: 'absolute' })
    },
    onRest: () => {
      setExtraStyle({ position: 'relative' })
    }
  })
  return (
    <div className="bg-#5f34bf" h-screen flex flex-col items-stretch pb-16px>
      <header shrink-0 text-center pt-64px>
        <img src={logo} w-64px h-69px />
        <h1 text="#D4D4EE" text-32px>山竹记账</h1>
      </header>
      <main shrink-1 grow-1 relative >
        {transitions((style, pathname) =>
          <animated.div key={pathname} style={{ ...style, ...extraStyle }} w="100%" h="100%" p-16px flex>
            <div grow-1 bg-white flex justify-center items-center rounded-8px>
              {map.current[pathname]}
            </div>
          </animated.div>
        )}
      </main>
      <footer shrink-0 text-center text-24px text-white grid grid-cols-3 grid-rows-1>
        <Link style={{ gridArea: '1 / 2 / 2 / 3' }} to={linkMap[location.pathname]}>下一页</Link>
        <Link style={{ gridArea: '1 / 3 / 2 / 4' }} to="/welcome/xxx">跳过</Link>
      </footer>
    </div>
  )
}