基于React实现居中卡片高亮、其余淡出的水平卡片滑块
实现居中卡片高亮的水平滑块方案
方案一:基于react-slick改造
react-slick本身支持centerMode模式,结合CSS就能实现淡出效果,步骤如下:
- 先安装依赖:
npm install react-slick slick-carousel
- 编写组件代码:
import React from 'react'; import Slider from 'react-slick'; // 引入slick的基础样式 import 'slick-carousel/slick/slick.css'; import 'slick-carousel/slick/slick-theme.css'; import './CustomSlider.css'; const HighlightSlider = () => { const sliderSettings = { centerMode: true, // 开启居中模式 centerPadding: '60px', // 两侧留白 slidesToShow: 3, // 同时显示3张卡片 infinite: true, speed: 500, arrows: true, dots: false, }; // 模拟卡片数据 const cardList = [1,2,3,4,5].map(num => ( <div className="slide-card" key={num}> <h3>Card {num}</h3> </div> )); return ( <div className="slider-container"> <Slider {...sliderSettings}> {cardList} </Slider> </div> ); }; export default HighlightSlider;
- 添加自定义CSS:
.slider-container { width: 80%; margin: 0 auto; } .slide-card { background: #fff; padding: 40px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); opacity: 0.5; /* 默认淡出 */ transition: all 0.3s ease; } /* 选中的居中卡片高亮 */ .slick-center .slide-card { opacity: 1; transform: scale(1.1); box-shadow: 0 4px 16px rgba(0,0,0,0.2); }
这个方案利用react-slick内置的slick-center类标记居中卡片,通过CSS控制透明度和样式,快速实现需求。
方案二:自定义滑块组件
如果需要更灵活的淡出逻辑(比如根据距离设置不同透明度),可以自己实现滑块:
import React, { useState, useRef, useEffect } from 'react'; import './CustomSlider.css'; const CustomHighlightSlider = () => { const [activeIndex, setActiveIndex] = useState(2); // 默认选中中间卡片 const sliderContainerRef = useRef(null); const cardList = [1,2,3,4,5]; // 监听滚动,自动计算居中的卡片 useEffect(() => { const handleScroll = () => { const container = sliderContainerRef.current; const scrollLeft = container.scrollLeft; const singleCardWidth = container.querySelector('.slide-card').offsetWidth; const centerOffset = container.offsetWidth / 2; // 计算当前居中的卡片索引 const currentIndex = Math.round((scrollLeft + centerOffset) / singleCardWidth); setActiveIndex(Math.max(0, Math.min(cardList.length - 1, currentIndex))); }; const container = sliderContainerRef.current; container.addEventListener('scroll', handleScroll); return () => container.removeEventListener('scroll', handleScroll); }, [cardList.length]); // 上一张按钮逻辑 const goToPrev = () => { const newIndex = Math.max(0, activeIndex - 1); setActiveIndex(newIndex); const container = sliderContainerRef.current; const singleCardWidth = container.querySelector('.slide-card').offsetWidth; container.scrollTo({ left: singleCardWidth * newIndex, behavior: 'smooth' }); }; // 下一张按钮逻辑 const goToNext = () => { const newIndex = Math.min(cardList.length - 1, activeIndex + 1); setActiveIndex(newIndex); const container = sliderContainerRef.current; const singleCardWidth = container.querySelector('.slide-card').offsetWidth; container.scrollTo({ left: singleCardWidth * newIndex, behavior: 'smooth' }); }; return ( <div className="custom-slider-wrapper"> <button onClick={goToPrev} className="slider-btn">←</button> <div className="custom-slider-container" ref={sliderContainerRef}> {cardList.map((num, index) => { // 根据与选中卡片的距离设置透明度 const distance = Math.abs(index - activeIndex); let opacity = 1; if (distance === 1) opacity = 0.7; else if (distance >= 2) opacity = 0.3; return ( <div className="slide-card" key={num} style={{ opacity, transition: 'opacity 0.3s ease' }} > <h3>Card {num}</h3> </div> ); })} </div> <button onClick={goToNext} className="slider-btn">→</button> </div> ); }; export default CustomHighlightSlider;
对应的CSS:
.custom-slider-wrapper { display: flex; align-items: center; justify-content: center; gap: 20px; width: 90%; margin: 0 auto; } .custom-slider-container { display: flex; gap: 20px; overflow-x: auto; scroll-behavior: smooth; padding: 20px 0; width: 100%; max-width: 800px; } /* 隐藏滚动条 */ .custom-slider-container::-webkit-scrollbar { display: none; } .slide-card { flex: 0 0 200px; background: #fff; padding: 40px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .slider-btn { padding: 10px 15px; font-size: 20px; border: none; background: #eee; border-radius: 4px; cursor: pointer; }
这个方案可以完全控制淡出规则,比如距离选中卡片越远,透明度越低,适合定制化需求高的场景。
内容的提问来源于stack exchange,提问作者missgoyal
相关产品推荐
相关产品推荐

