第一种是点击tab会切换,url改变,同时在切换的时候有轮播图的效果
一开始我想的是用slidesPerview来实现这种一版有多个card,这样就做不了history的跳转,官方给的history demo一个版只有一个slide,如果要做路由history的控制,就得用Mui的Grid来实现。
javascript
<SwiperSlide style={{ height: "100%", width: "100%", marginBottom: "30px" }} data-history="trending" >
<Grid
container
columns={{ xs: 4, sm: 8, md: 12 }}
rowSpacing={3} columnSpacing={{ xs: 1, sm: 2, md: 3 }}
style={{ height: "100%", marginTop: "20px", width: "100%" }}
>
{Array.from(Array(16)).map((_, index) => (
<Grid xs={2} sm={3} md={3} key={index}>
<Item><MarketCard /></Item>
</Grid>
))}
</Grid>
</SwiperSlide>

这样子就可以有每个Slide都有6个card,之后要做上面的tab切换,注意url栏,是会跟着改变的。这里我一开始是在swiper的history demo(codesandbox.io/s/nshsvn?fi...)里看,发现改了url就会出现对应的slide:

我就想点击tab组件去改url,然后就可以渲染对应的slide,,结果不行,因为项目用的是next.js,如果是用tab组件,确实能够改变url, 但是没有渲染对应的,因为slide它没有对应一个页面,那么该url就没有对应一个路由,就会报错。然后我又想,那就创建一个对应的slide页面吧:

然后在页面里面用类似Layout的组件去包裹:
xml
<TabSwiper>
<SwiperSlide style={{ height: "100%", marginBottom: "30px" }} data-history="new" >
<Grid
container
// spacing={{ xs: 2, md: 13 }}
// bgcolor="#FFF"
columns={{ xs: 4, sm: 8, md: 12 }}
rowSpacing={3} columnSpacing={{ xs: 1, sm: 2, md: 3 }}
style={{ height: "100%", marginTop: "20px", width: "100%" }}
>
slide2
{Array.from(Array(16)).map((_, index) => (
<Grid xs={2} sm={3} md={3} key={index}>
<Item><MarketCard /></Item>
</Grid>
))}
</Grid>
</SwiperSlide>
</TabSwiper>
这里的TabSwiper就相当于Layout。这样子点击tab是能够切换到对应的slide的了,这里还有个致命的问题:我在切换tab的时候并没有swiper的效果,就是很生硬的跳转,所以我采用另一种方法来实现tab:修改pagination。
pagination本来只是一些圆点和数字,因为点击它可以切换slide,而且路由也跟着改变,所以非常适合改成tab,我们要的tab就是要实现类似的功能:
自定义Pagination:
javascript
const pagination = {
el: '.swiper-pagination',
clickable: true,
modifierClass: "custom-modifier-class",
horizontalClass: "custom-horizontal-class",
bulletClass: 'custom-pagination-bullet', // Custom class for pagination bullets
bulletActiveClass: 'custom-pagination-bullet-active',
renderBullet: function (index, className) {
return (
'<span class="' + className + '">' + (tabs[index].label) + '</span>'
);
},
};
这个swiper的全部实现代码:
javascript
import React from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import { Box, } from '@mui/material'
import Grid from '@mui/material/Unstable_Grid2';
import { CSSProperties } from 'react';
import 'swiper/css';
import 'swiper/css/grid';
import 'swiper/css/pagination';
import { Pagination, History } from 'swiper/modules';
import { experimentalStyled as styled } from '@mui/material/styles';
import Paper from '@mui/material/Paper';
import styles from './styles.module.css';
import MarketCard from '../../../components/Market/MarketCard'
import NavTabs from './NavTab';
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
...theme.typography.body2,
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
}));
const tabs = [
{ label: 'Trending', href: '/Home/TabSwiper/slides/trending' },
{ label: 'New', href: '/Home/TabSwiper/slides/new' },
{ label: 'Ending Soon', href: '/slides/ending' },
{ label: 'Volume', href: '/slides/volume' },
{ label: 'Liquidity', href: '/slides/liquidity' },
];
export default function TabSwiper() {
const pagination = {
el: '.swiper-pagination',
clickable: true,
modifierClass: "custom-modifier-class",
horizontalClass: "custom-horizontal-class",
bulletClass: 'custom-pagination-bullet', // Custom class for pagination bullets
bulletActiveClass: 'custom-pagination-bullet-active',
renderBullet: function (index, className) {
return (
'<span class="' + className + '">' + (tabs[index].label) + '</span>'
);
},
};
return (
<>
<div className="swiper-pagination"></div>
<Box sx={{ position: "relative", height: "68rem", width: "100%", }}>
<Swiper
slidesPerView={1}
grid={{
fill: "row",
rows: 1,
}}
spaceBetween={30}
history={{
key: '/home/tabswiper/slides',
}}
pagination={pagination}
modules={[Pagination, History]}
className={styles.swiper}
>
<SwiperSlide style={{ height: "100%", width: "100%", marginBottom: "30px" }} data-history="trending" >
<Grid
container
columns={{ xs: 4, sm: 8, md: 12 }}
rowSpacing={3} columnSpacing={{ xs: 1, sm: 2, md: 3 }}
style={{ height: "100%", marginTop: "20px", width: "100%" }}
>
{Array.from(Array(16)).map((_, index) => (
<Grid xs={2} sm={3} md={3} key={index}>
<Item><MarketCard /></Item>
</Grid>
))}
</Grid>
</SwiperSlide>
<SwiperSlide style={{ height: "100%", marginBottom: "30px" }} data-history="new" >
<Grid
container
columns={{ xs: 4, sm: 8, md: 12 }}
rowSpacing={3} columnSpacing={{ xs: 1, sm: 2, md: 3 }}
style={{ height: "100%", marginTop: "20px", width: "100%" }}
>
slide2
{Array.from(Array(16)).map((_, index) => (
<Grid xs={2} sm={3} md={3} key={index}>
<Item><MarketCard /></Item>
</Grid>
))}
</Grid>
</SwiperSlide>
<SwiperSlide style={{ height: "100%", marginBottom: "30px" }} data-history="ending" >Custom Slide 3</SwiperSlide>
<SwiperSlide style={{ height: "100%", marginBottom: "30px" }} data-history="volume" >Custom Slide 4</SwiperSlide>
<SwiperSlide style={{ height: "100%", marginBottom: "30px" }} data-history="liquidity" >Custom Slide 5</SwiperSlide>
</Swiper>
</Box>
</>
);
}
第二种Swiper:

除了这个效果,UI还要实现悬浮在某个card,某个card就扩大的效果。
这个就用到了SlidePerview。此外还有一点和原本swiper提供的组件不太一样的就是它的左右按钮,需要我们自己加上去。
详细代码:
悬浮在card后,card就会变大:在原有 SwiperSlide的基础上自定义一个slide
less
const StyledSwiperSlide = styled(SwiperSlide)(({ theme }) => ({
// Your slide styles here
position: "relative", /* Ensure positioning context */
transition: "transform 0.3s ease",
// Add hover effect
'& :hover': {
transform: 'scale(1.03)', // Scale up the slide by 5% on hover
zIndex: 2, // Optional: Adjust z-index for layering
boxShadow: '0px 0px 10px rgba(0, 0, 0, 0.3)', // Optional: Add a shadow
},
}));
增加左右按钮:以右边(上一页)的按钮为例
arduino
<Box
className='custom-prev-button'
sx={{
justifyContent: "center",
alignItems: "center",
position: "absolute",
top: "calc(50% - 20px)",
borderRadius: "10px",
boxShadow: "var(--shadows-dropShadowSm)",
zIndex: 999,
transition: " all 0.2s ease 0s",
cursor: "pointer",
display: "flex",
left: "-16px",
opacity: 1
}}
>
<Image src={pre} alt="" width="40" height="40" />
</Box>
然后将这两个按钮放在Swiper外面就可以:

最终效果:
