使用方式
npm i react-carousel-new
代码示例👇:
import React from 'react';
import { Carousel } from 'react-carousel-new';
const Com: React.FC = () => {
return (
<div style={{
width: '100%',
height: '500px',
}}>
<Carousel
centerImage="https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500"
surroundingImages={[
"https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500",
"https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500",
"https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500",
"https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500",
"https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500",
"https://img0.baidu.com/it/u=1241597997,3770576363&fm=253&fmt=auto&app=138&f=JPEG?w=732&h=500",
]}
/>
</div>
);
};
export default Com;
API
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
centerImage | 中心图片 | string | - |
surroundingImages | 周围图片 | string[] | - |
speed | 旋转速度 | number | 0.5 |
radius | 半径 | number | 300 |
className | 自定义类名 | string | - |
实现原理
3D跑马灯(旋转木马)特效主要通过CSS 3D变换和JavaScript动画控制实现。核心是利用transform
属性的rotateY
和translateZ
组合,将平面元素转换为三维空间中的环形布局。
旋转动画通过持续修改旋转角度来实现,通常使用requestAnimationFrame
保证流畅性。元素在Y轴旋转的同时沿Z轴位移,形成立体环绕效果。
React组件实现方法
基础组件结构
import React, { useState, useEffect, useRef } from 'react';
interface CarouselProps {
items: Array<{ id: string; content: React.ReactNode }>;
radius?: number;
speed?: number;
}
const Carousel3D: React.FC<CarouselProps> = ({
items,
radius = 300,
speed = 0.5
}) => {
const [angle, setAngle] = useState(0);
const animationRef = useRef<number>();
useEffect(() => {
const animate = () => {
setAngle(prev => (prev + speed) % 360);
animationRef.current = requestAnimationFrame(animate);
};
animationRef.current = requestAnimationFrame(animate);
return () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, [speed]);
return (
<div className="carousel-container">
{items.map((item, index) => {
const itemAngle = (index * (360 / items.length)) + angle;
return (
<div
key={item.id}
className="carousel-item"
style={{
transform: `rotateY(${itemAngle}deg) translateZ(${radius}px)`
}}
>
{item.content}
</div>
);
})}
</div>
);
};
CSS样式配置
.carousel-container {
position: relative;
width: 100%;
height: 400px;
perspective: 1000px;
transform-style: preserve-3d;
}
.carousel-item {
position: absolute;
width: 200px;
height: 200px;
top: 50%;
left: 50%;
transform-origin: center center;
transition: transform 0.1s ease-out;
backface-visibility: visible;
}
高级功能扩展
自动暂停与交互控制
const [isPlaying, setIsPlaying] = useState(true);
useEffect(() => {
if (!isPlaying && animationRef.current) {
cancelAnimationFrame(animationRef.current);
return;
}
// ...原有动画逻辑
}, [isPlaying, speed]);
const handleItemClick = (index: number) => {
const targetAngle = 360 - (index * (360 / items.length));
setAngle(targetAngle);
};
响应式半径调整
const [dynamicRadius, setDynamicRadius] = useState(radius);
useEffect(() => {
const handleResize = () => {
setDynamicRadius(Math.min(radius, window.innerWidth * 0.3));
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [radius]);
性能优化建议
使用will-change
属性提前告知浏览器可能的变化
.carousel-item {
will-change: transform;
}
对静态内容使用React.memo
const MemoizedItem = React.memo(({ content }: { content: React.ReactNode }) => (
<div className="item-content">{content}</div>
));