撸一个掘金APP会员等级轮播

使用的是我之前开发的开源库 bear-react-carousel

主要试试看能做到什么程度,之前公司也有类似的需求

废话不多说,直接开始

需求

首先我们先看掘金在APP端的预览结果

  • 可滑动的部分只有 卡片的部分
  • 并且在滑动时等级卡片会往上移动
  • 等级卡片显示为置中为 选中项目
  • 等级卡片下方需要被遮住(圆弧),不显示完全
  • 等级名称项目需同步移动
  • 等级名称项目移动时圆弧移动
  • 等级名称线需同步移动
  • API 捞回时,预设需要移动到选中的等级(无动画移动)

开发轮播项目

轮播项目可以切分为:

  • 等级卡片,显示1.2个并且置
tsx 复制代码
<BearCarousel
    slidesPerView={1.2}
    spaceBetween={20}
    isCenteredSlides={true}
    // ...ignore
/>
  • 等级名称
  • 等级线 这两个都是显示3个并且置中
tsx 复制代码
<BearCarousel
    slidesPerView={3}
    isCenteredSlides={true}
    // ...ignore
/>

所以开发目标是 移动等级卡片时,同步移动 等级名称等级线

tsx 复制代码
import React, {useCallback, useEffect, useRef, useState} from 'react';
import BearCarousel, {TMoveEffectFn, TBearSlideItemDataList, BearSlideCard, elClassName, Controller, TOnSlideChange} from 'bear-react-carousel';

const MemberLevelWrapper = () => {
   const carouselMainRef = useRef<BearCarousel>(null);
   const carouselMetaRef = useRef<BearCarousel>(null);
   const carouselLineRef = useRef<BearCarousel>(null);

   return <>
        {/* 等级卡片 */}
        <BearCarousel
            ref={carouselMainRef}
            syncCarouselRefs={[carouselMetaRef, carouselLineRef]}
            slidesPerView={1.2}
            spaceBetween={20}
            isCenteredSlides={true}
            // ...ignore
        />

        {/* 等级名称 */}
        <BearCarousel
            ref={carouselMetaRef}
            // ...ignore
        />

        {/* 等级名称线 */}
        <BearCarousel
            ref={carouselLineRef}
            // ...ignore
        />
    </>;
};    

然后再来是 滑动时等级卡片会往上移动, 新增一个 动画 effect function

tsx 复制代码
import BearCarousel, {TMoveEffectFn} from 'bear-react-carousel';

const mainMoveEffectFn: TMoveEffectFn = useCallback((percentageInfo) => {
    const transformY = 40;
    return {
        transform: `translate(0px, ${-transformY * (percentageInfo.calcPercentage - 1)}px)`,
    };
}, []);

<BearCarousel
    ref={carouselMainRef}
    syncCarouselRefs={[carouselMetaRef, carouselLineRef]}
    moveEffect={{
        moveFn: mainMoveEffectFn,
    }}
    // ...ignore
/>

等级名称的圆弧移动

tsx 复制代码
const levelNameMoveEffectFn: TMoveEffectFn = useCallback((percentageInfo) => {
    const transformY = -19;
    return {
        transform: `translate(0px, ${-transformY * (percentageInfo.calcPercentage - 1)}px)`,
    };
}, []);

<BearCarousel
    ref={carouselMainRef}
    moveEffect={{
        moveFn: levelNameMoveEffectFn,
    }}
    // ...ignore
/>

至于圆弧的部分,我们最后使用遮罩的方式来显示,并且关闭 NavButton、Pagination、MouseMove,画SVG不熟的话,可以使用这个工具 yqnn.github.io/svg-path-ed...

tsx 复制代码
<LevelLine>
    <LineBearCarousel
        ref={carouselLineRef}
        data={lineData}       
        slidesPerView={3}
        isCenteredSlides={true}
        isEnableNavButton={false}
        isEnablePagination={false}
        isEnableMouseMove={false}
    />

    <svg height="100%" width="100%">
        <clipPath id="wave12">
            {/*跟隨線*/}
            <path d="M 0 4 C 175 30 175 30 356 4 L 356 2 C 175 28 175 28 0 2" stroke="black" fill="transparent"/>
        </clipPath>
    </svg>
</LevelLine>

而 Level Card 遮罩的部分一样,但我用了3块

tsx 复制代码
<svg height="100%" width="100%">
    <clipPath id="wave10">
        <path d="M 0,0 356,0 356,130 0,130" stroke="black" fill="transparent"/>
        {/* 圓弧 */}
        <path d="M 0 130 C 175 155 175 155 356 130" stroke="black" fill="transparent"/>
         {/* 下箭頭 */}
        <path d="M 152 143 L 176 153 L 178 153 L 202 143" stroke="black" fill="transparent"/>
    </clipPath>
</svg>

最后就是 预设选中等级的部分(无动画方式移动)

tsx 复制代码
const [carouselMainController, setMainController] = useState<Controller>();
const [currLevel, setCurrLevel] = useState<{lv: number,count: number}|undefined>();


useEffect(() => {
    carouselMainController?.slideToPage(5, false);
}, [carouselMainController]);


<BearCarousel
    ref={carouselMainRef}
    syncCarouselRefs={[carouselMetaRef]}
    onSlideChange={handleSlideChange}
    setController={setMainController}
    slidesPerView={1.2}
    spaceBetween={20}
    isCenteredSlides={true}
    // ...ignore
/>

完成

目前成果作为文件的展示使用,想试试看的客观可以实际操作看看

bear-react-carousel.pages.dev/

以上就完成了,基本上如果两边都需要移动的话,互相同步在bear-react-carousel 因为是进行独立的同步控制,所以不会循环互控,但也因为这样所以目前是无法A控制B , B自动再控制C,所以在这边可以发现是A控制B和C。

相关推荐
贵沫末17 分钟前
React——基础
前端·react.js·前端框架
aklry28 分钟前
uniapp三步完成一维码的生成
前端·vue.js
Rubin9336 分钟前
判断元素在可视区域?用于滚动加载,数据埋点等
前端
爱学习的茄子36 分钟前
AI驱动的单词学习应用:从图片识别到语音合成的完整实现
前端·深度学习·react.js
用户38022585982437 分钟前
使用three.js实现3D地球
前端·three.js
程序无bug39 分钟前
Spring 面向切面编程AOP 详细讲解
java·前端
zhanshuo39 分钟前
鸿蒙UI开发全解:JS与Java双引擎实战指南
前端·javascript·harmonyos
JohnYan39 分钟前
模板+数据的文档生成技术方案设计和实现
javascript·后端·架构
撰卢1 小时前
如何提高网站加载速度速度
前端·javascript·css·html
10年前端老司机1 小时前
在React项目中如何封装一个可扩展,复用性强的组件
前端·javascript·react.js