forked from 77media/video-flow
新增 h5视频使用card效果
This commit is contained in:
parent
0ec9fc39b8
commit
7e49b48d0f
@ -276,7 +276,7 @@ export function HomePage2() {
|
|||||||
</LazyLoad>
|
</LazyLoad>
|
||||||
{/* 动态锚点:来源于服务端 homeTab 配置,title 作为锚点与标题 */}
|
{/* 动态锚点:来源于服务端 homeTab 配置,title 作为锚点与标题 */}
|
||||||
{homeTabs.map((tab) => (
|
{homeTabs.map((tab) => (
|
||||||
<div key={tab.title} data-test={JSON.stringify(tab)} data-alt={`anchor-${tab.title.toLowerCase()}`} ref={(el) => (sectionRefs.current as any)[tab.title.toLowerCase()] = el}>
|
<div key={tab.title} data-alt={`anchor-${tab.title.toLowerCase()}`} ref={(el) => (sectionRefs.current as any)[tab.title.toLowerCase()] = el}>
|
||||||
<VideoCoverflow title={tab.title} subtitle={tab.subtitle} videos={tab.videos} />
|
<VideoCoverflow title={tab.title} subtitle={tab.subtitle} videos={tab.videos} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
import { Autoplay, EffectCoverflow } from 'swiper/modules';
|
import { Autoplay, EffectCoverflow, EffectCards } from 'swiper/modules';
|
||||||
import type { Swiper as SwiperType } from 'swiper/types';
|
import type { Swiper as SwiperType } from 'swiper/types';
|
||||||
|
import { useDeviceType } from '@/hooks/useDeviceType';
|
||||||
|
|
||||||
import 'swiper/css';
|
import 'swiper/css';
|
||||||
import 'swiper/css/effect-coverflow';
|
import 'swiper/css/effect-coverflow';
|
||||||
|
import 'swiper/css/effect-cards';
|
||||||
|
|
||||||
/** 默认视频列表(来自 home-page2.tsx 中的数组) */
|
/** 默认视频列表(来自 home-page2.tsx 中的数组) */
|
||||||
const DEFAULT_VIDEOS: string[] = [
|
const DEFAULT_VIDEOS: string[] = [
|
||||||
@ -40,21 +42,22 @@ const VideoCoverflow: React.FC<VideoCoverflowProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const swiperRef = React.useRef<SwiperType | null>(null);
|
const swiperRef = React.useRef<SwiperType | null>(null);
|
||||||
const videoRefs = React.useRef<Record<number, HTMLVideoElement | null>>({});
|
const videoRefs = React.useRef<Record<number, HTMLVideoElement | null>>({});
|
||||||
const [isMobile, setIsMobile] = React.useState<boolean>(false);
|
const { isMobile } = useDeviceType();
|
||||||
const [activeIndex, setActiveIndex] = React.useState<number>(0);
|
const [activeIndex, setActiveIndex] = React.useState<number>(0);
|
||||||
|
|
||||||
const playActive = React.useCallback((activeIndex: number) => {
|
const playActive = React.useCallback((activeIndex: number) => {
|
||||||
Object.entries(videoRefs.current).forEach(([key, el]) => {
|
Object.entries(videoRefs.current).forEach(([key, el]) => {
|
||||||
if (!el) return;
|
const video = el as HTMLVideoElement | null;
|
||||||
|
if (!video) return;
|
||||||
const index = Number(key);
|
const index = Number(key);
|
||||||
if (index === activeIndex) {
|
if (index === activeIndex) {
|
||||||
// 尝试播放当前居中视频
|
// 尝试播放当前居中视频
|
||||||
el.play().catch(() => {});
|
video.play().catch(() => {});
|
||||||
} else {
|
} else {
|
||||||
// 暂停其他视频,重置到起点以减少解码负担
|
// 暂停其他视频,重置到起点以减少解码负担
|
||||||
el.pause();
|
video.pause();
|
||||||
try {
|
try {
|
||||||
el.currentTime = 0;
|
video.currentTime = 0;
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -115,28 +118,32 @@ const VideoCoverflow: React.FC<VideoCoverflowProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
<div data-alt="video-coverflow" className="w-screen sm:w-full mx-auto overflow-hidden">
|
<div data-alt="video-coverflow" className="w-screen sm:w-full mx-auto overflow-hidden">
|
||||||
<Swiper
|
<Swiper
|
||||||
modules={[Autoplay, EffectCoverflow]}
|
modules={isMobile ? [Autoplay, EffectCards] : [Autoplay, EffectCoverflow]}
|
||||||
effect="coverflow"
|
effect={isMobile ? 'cards' : 'coverflow'}
|
||||||
|
key={isMobile ? 'cards' : 'coverflow'}
|
||||||
|
data-test={isMobile}
|
||||||
centeredSlides
|
centeredSlides
|
||||||
slidesPerView={isMobile ? 1 : 2}
|
slidesPerView={isMobile ? 1 : 2}
|
||||||
loop
|
loop
|
||||||
autoplay={{ delay: autoplayDelay, disableOnInteraction: false }}
|
autoplay={{ delay: autoplayDelay, disableOnInteraction: false }}
|
||||||
speed={1000}
|
speed={1000}
|
||||||
coverflowEffect={{
|
{...(!isMobile ? {
|
||||||
rotate: -56,
|
coverflowEffect: {
|
||||||
stretch: 10,
|
rotate: -56,
|
||||||
depth: 80,
|
stretch: 10,
|
||||||
scale: 0.6,
|
depth: 80,
|
||||||
modifier: 1,
|
scale: 0.6,
|
||||||
slideShadows: true,
|
modifier: 1,
|
||||||
}}
|
slideShadows: true,
|
||||||
|
},
|
||||||
|
} : {})}
|
||||||
onAfterInit={handleAfterInit}
|
onAfterInit={handleAfterInit}
|
||||||
onSlideChange={handleSlideChange}
|
onSlideChange={handleSlideChange}
|
||||||
className="w-full py-8"
|
className="w-full py-8"
|
||||||
>
|
>
|
||||||
{videos.map((src, index) => (
|
{videos.map((src, index) => (
|
||||||
<SwiperSlide key={src} className="select-none">
|
<SwiperSlide key={src} className="select-none">
|
||||||
<div data-alt="video-card" className={`${isMobile ? (activeIndex === index ? 'w-screen' : 'w-[80vw]') : 'w-[48vw]'} mx-auto aspect-video overflow-hidden rounded-xl shadow-lg`}>
|
<div data-alt="video-card" className={`${isMobile ? 'w-screen' : 'w-[48vw]'} mx-auto aspect-video overflow-hidden rounded-xl shadow-lg`}>
|
||||||
<video
|
<video
|
||||||
data-alt="video"
|
data-alt="video"
|
||||||
ref={(el) => { videoRefs.current[index] = el; }}
|
ref={(el) => { videoRefs.current[index] = el; }}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user