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

相关推荐
2501_9153738838 分钟前
electron+vite+vue3 快速入门教程
前端·javascript·electron
zhl9999999991 小时前
xe-upload上传文件插件
前端·上传文件·xe-upload·兼容app上传文件
宁酱醇2 小时前
CSS基础_@拉钩教育【笔记】
前端·css
建群新人小猿3 小时前
CRMEB-PRO系统定时任务扩展开发指南
android·java·开发语言·前端
牧天白衣.3 小时前
vue 和 html 的区别
前端
知识分享小能手3 小时前
JavaScript学习教程,从入门到精通,Ajax数据交换格式与跨域处理(26)
xml·开发语言·前端·javascript·学习·ajax·css3
好名字08213 小时前
el-tabs与table样式冲突导致高度失效问题解决(vue2+elementui)
前端·vue.js·elementui
qq_278063713 小时前
vue elementui 去掉默认填充 密码input导致的默认填充
前端·vue.js·elementui
黄同学real3 小时前
HTML5 新增的主要标签整理
前端·html·html5
liwulin05063 小时前
【JAVAFX】实现屏幕指定区域截图,带尺寸显示
服务器·前端·python