改造微信小程序Swiper组件,自定义切换动画

index.tsx

TypeScript 复制代码
import { FC, memo, PropsWithChildren, useEffect, useState, useRef, useMemo } from 'react'
import { Swiper as BaseSwiper, SwiperItem, View } from '@tarojs/components'
import { Button } from '@wmeimob/taro-design'
import classNames from 'classnames'
import styles from './index.module.less'
import Taro from '@tarojs/taro'
import { Flex } from '~/components'
import { vibrateShort } from '~/utils/util'
import { SwiperProps } from './const'
// import { getBarHeight } from '~/pages/service/util'

/**
 * Swiper
 * @param props
 * @returns
 */
const Component: FC<PropsWithChildren<SwiperProps>> = ({ current, modes, isDot, onMode, children }) => {
  const [currentIndex, setCurrentIndex] = useState(current ?? 0)
  // const [dx, setDx] = useState(0)
  const currentRef = useRef<number>(0)

  useEffect(() => {
    setCurrentIndex(current)
    return () => {
      Taro.setStorageSync('U1_LASTTIME_MODE_CURRENT', currentRef.current)
    }
  }, [current])
 
  // const getScale = useMemo(() => {
  //   const { windowWidth } = Taro.getSystemInfoSync()
  //   return Math.min(Math.max(dx / (windowWidth - 20), 0.88), 1)
  // }, [dx])
  // console.log('Taro', Taro.getSystemInfoSync().windowWidth, getScale)

  return (
    <View className={styles.container}>
      <BaseSwiper
        // autoplay
        // interval={2500}
        easingFunction='easeOutCubic'
        circular
        duration={1000}
        previousMargin='8px'
        nextMargin='12px'
        current={currentIndex}
        className={styles.swiperBox}
        onChange={(event) => {
          setCurrentIndex(event.detail.current)
          currentRef.current = event.detail.current
          vibrateShort()
        }}
        // style={{
        //   height: Taro.getSystemInfoSync().windowHeight - getBarHeight() - 44 - 34
        // }}
        // onTransition={(event) => {
        //   console.log('onTransition', event.detail.dx)
        //   setDx(event.detail.dx)
        // }}
      >
        {modes.map((mode, index) => {
          return (
            <SwiperItem key={`key-${index}`}>
              <Flex
                column
                style={{
                  backgroundImage: `url(${mode?.bgImg})`
                  // transform: index === currentIndex ? ` scale(${getScale})` : undefined
                }}
                className={classNames(styles.swiperItem,{
                  [styles.swiperItemActive]: index === currentIndex,
                  [styles.swiperItemOutRight]: index > currentIndex,
                  [styles.swiperItemOutLeft]: index < currentIndex
                })}
              >
                <Button
                    className={styles.button}
                    type="main"
                    text='开始护肤'
                    onClick={(event) => {
                      event.stopPropagation()
                      onMode?.(mode)
                    }}
                   />
              </Flex>
            </SwiperItem>
          )
        })}
      </BaseSwiper>
      {isDot && (
        <Flex alignCenter className={styles.dots}>
          {modes.map((_, index) => {
            return (
              <View
                key={`key-${index}`}
                className={classNames(styles.dot, {
                  [styles.dotActive]: index === currentIndex
                })}
              />
            )
          })}
        </Flex>
      )}
      {children}
    </View>
  )
}

const Swiper = memo(Component)
export default Swiper

index.less

css 复制代码
.container {
  position: relative;
}

.swiperBox {
  position: relative;
  width: 100vw;
  height: calc(100vw * 638 / 375);

  .swiperItem {
    position: relative;
    width: calc(100% - 5px);
    height: 100%;
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
    border-radius: 8px;
    margin-left: 5px;
    padding: 15px;

    .button {
      position: absolute;
      top: calc(100vw * 175 / 375);
      
      width: 130px;
      height: 42px;
      
      border-radius: 42px;
      background: #EFD7B1;
      font-weight: 500;
    }
  }

  .swiperItemActive {
    transform: scale(1);
    transition: all 0.8s ease 0s;
  }

  .swiperItemOutLeft {
    transition: all 0.8s ease-out 0.1s;
    transform: translate(20px, 38px) scale(0.88);
  }

  .swiperItemOutRight {
    transition: all 0.8s ease-out 0.1s;
    transform: translate(-20px, 38px) scale(0.88);
  }
}

.dots {
  position: absolute;
  bottom: -15px;
  // gap: 5px; // 有些手机型号无效
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;

  .dot {
    width: 12px;
    height: 2px;
    background-color: #5B5C5C;
    transition: all 0.5s;
    margin-right: 5px;
  }

  .dotActive {
    background-color: #fff;
  }
}

conts.ts

TypeScript 复制代码
export interface SwiperProps {
  current: number
  modes: xxxx[] // xxx是需要定义的inteface结构
  isDot?: boolean
  onMode?: (plan: CareModelDTO) => void
}

改造Swiper组件,符合业务的设计和动画效果

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄2 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端