改造微信小程序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组件,符合业务的设计和动画效果

相关推荐
Wang's Blog1 小时前
Webpack: 持久化缓存大幅提升构建性能
前端·缓存·webpack
程序员储物箱1 小时前
Vue报错:Module not found: Error: Can‘t resolve ‘less-loader‘ in ‘文件地址‘
前端·vue
乐吾乐科技1 小时前
【国产开源可视化引擎Meta2d.js】锚点
前端·编辑器·web·数据可视化·大屏端
Her...1 小时前
electron教程(一)创建项目
前端·javascript·electron
logstach2 小时前
QML-Grid和OpacityMask
前端·qml
C+ 安口木3 小时前
前端代码规范 - 日志打印规范
前端·代码规范
朝阳393 小时前
js【最佳实践】遍历数组的八种方法(含数组遍历 API 的对比)for,forEach,for of,map,filter,reduce,every,some
javascript
Jesse_Kyrie3 小时前
配置windows环境下独立浏览器爬虫方案【不依赖系统环境与chrome】
前端·chrome·爬虫·python·scrapy
copyer_xyf5 小时前
文件上传
前端·javascript
野槐5 小时前
CSS原子化
前端·css