撸一个掘金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。

相关推荐
二狗哈11 小时前
Cesium快速入门17:与entity和primitive交互
开发语言·前端·javascript·3d·webgl·cesium·地图可视化
xingzhemengyou111 小时前
python datetime模块使用
前端·python
GISer_Jing12 小时前
AI驱动营销增长:7大核心场景与前端实现
前端·javascript·人工智能
星光不问赶路人12 小时前
new Array() 与 Array.from() 的差异与陷阱
javascript·面试
T___T12 小时前
Vue 3 做 todos , ref 能看懂,computed 终于也懂了
前端·javascript·面试
bug总结12 小时前
vue+A*算法+canvas解决自动寻路方案
前端·vue.js·算法
cindershade12 小时前
JavaScript 事件循环机制详解及项目中的应用
前端·javascript
王霸天12 小时前
🚀 告别“变形”与“留白”:前端可视化大屏适配的终极方案(附源码)
前端·javascript
LYFlied12 小时前
Vue版本演进:Vue3、Vue2.7与Vue2全面对比
前端·javascript·vue.js
PieroPC12 小时前
Nicegui 组件放在页面中间
前端·后端