123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import React, { useCallback, useEffect, useRef, useState } from 'react'
- import Slider from 'react-slick'
- import 'slick-carousel/slick/slick.css'
- import 'slick-carousel/slick/slick-theme.css'
- import classNames from 'classnames'
- import styles from './index.module.scss' // 自定义样式
- type Slide = {
- id: number
- background: string
- content: React.ReactNode
- }
- const VerticalBanner: React.FC<{ slides: Slide[] }> = ({ slides }) => {
- const sliderRef = useRef<Slider>(null)
- const isScrolling = useRef(false)
- const [activeIndex, setActiveIndex] = useState<number | undefined>(undefined)
- // 垂直轮播配置
- const settings = {
- dots: true,
- dotsClass: 'slick-dots vertical-dots', // 自定义垂直dots样式
- infinite: true,
- speed: 800,
- slidesToShow: 1,
- slidesToScroll: 1,
- arrows: false,
- autoplay: false,
- adaptiveHeight: true,
- initialSlide: 0,
- afterChange: (index: number) => {
- setActiveIndex(index)
- }
- }
- // 处理滚轮事件
- const handleWheel = useCallback((e: WheelEvent) => {
- if (isScrolling.current) return
- // 阻止页面默认滚动
- e.preventDefault()
- // 设置滚动锁定,避免连续触发
- isScrolling.current = true
- setTimeout(() => {
- isScrolling.current = false
- }, 1000) // 滚动动画期间锁定
- // 根据滚轮方向切换幻灯片
- if (e.deltaY > 0) {
- sliderRef.current?.slickNext()
- } else {
- sliderRef.current?.slickPrev()
- }
- }, [])
- // 注册滚轮事件
- useEffect(() => {
- setTimeout(() => {
- setActiveIndex(0)
- }, 300)
- const handleScroll = (e: WheelEvent) => {
- // 仅在组件挂载时处理
- if (sliderRef.current) {
- handleWheel(e)
- }
- }
- // 添加滚轮事件监听器
- window.addEventListener('wheel', handleScroll, { passive: false })
- return () => {
- // 组件卸载时移除监听器
- window.removeEventListener('wheel', handleScroll)
- }
- }, [handleWheel])
- return (
- <div className={styles.banner}>
- <Slider ref={sliderRef} {...settings}>
- {slides.map((slide, index) => {
- const isActive = activeIndex === index
- return (
- <div key={slide.id} className='fullscreen-slide'>
- <div className={classNames('slide-content', { animate: isActive })} style={{ background: `url(${slide.background}) no-repeat center center/cover` }}>
- {slide.content}
- </div>
- </div>
- )
- })}
- </Slider>
- </div>
- )
- }
- export default VerticalBanner
|