Reactjs 反应:转盘第一张幻灯片转到最后一张幻灯片
我正在为我的应用程序使用React-Typescript。对于样式,我使用[styled components]。我已经做了一个自定义旋转木马图像,它的作品很好。但是我想当幻灯片转到最后一张图片时,它会像这样Reactjs 反应:转盘第一张幻灯片转到最后一张幻灯片,reactjs,typescript,carousel,styled-components,slide,Reactjs,Typescript,Carousel,Styled Components,Slide,我正在为我的应用程序使用React-Typescript。对于样式,我使用[styled components]。我已经做了一个自定义旋转木马图像,它的作品很好。但是我想当幻灯片转到最后一张图片时,它会像这样[1][2][3][4][1]但是现在它的行为像这样[1][2][3][4]。我想要旋转木马。但我的逻辑不起作用 我在中共享我的代码 这是我的应用程序组件,其中图像数组传递到旋转木马组件 import * as React from "react"; import &qu
[1][2][3][4][1]
但是现在它的行为像这样[1][2][3][4]
。我想要旋转木马。但我的逻辑不起作用
我在中共享我的代码
这是我的应用程序组件,其中图像数组传递到旋转木马组件
import * as React from "react";
import "./styles.css";
import Carousel from "./carousel";
export const imgUrls = [
`https://images.unsplash.com/photo-1455849318743-b2233052fcff?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1494253109108-2e30c049369b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`
];
export default function App() {
return (
<div className="App">
<Carousel slides={imgUrls} autoPlay dots />
</div>
);
}
import React, { useState, useEffect, useRef, memo, useCallback } from "react";
import styled from "styled-components";
export interface ICarousel {
children: JSX.Element[];
currentSlide?: number;
autoPlay?: boolean;
dots?: boolean;
interval?: number;
arrow?: boolean;
slideTest?: number;
}
const IMG_WIDTH = 320;
const IMG_HEIGHT = 700;
export default memo(
({
autoPlay = false,
dots = false,
interval = 2000,
arrow = false,
slideTest,
slides // This is my props which is coming from parent,
}: ICarousel) => {
const [savedSlides, setSavedSlides] = useState([]);
const [currentSlide, setSlide] = useState(0);
const [isPlaying, setIsPlaying] = useState(autoPlay);
const timer = useRef<any>(undefined);
useEffect(() => {
setSavedSlides(
slides?.map((slide, index) => {
return (
<CarouselSlide key={slide}>
<img
key={slide}
src={slide}
alt={`Example of mobile application ${index}`}
style={{
borderRadius: `20px`
}}
/>
</CarouselSlide>
);
})
);
}, [slides]);
// console.log(savedSlides);
// console.log(savedSlides.length);
const handleSlideChange = useCallback(
(index: number) => {
// IN here I made the condition but it does not work what I am expecting .
// I want the first will go all the way to last slide
setSlide(
index > savedSlides.length - 1
? 0
: index < 0
? savedSlides.length - 1
: index
);
},
[savedSlides]
);
const createInterval = useCallback(() => {
timer.current = setInterval(() => {
handleSlideChange(currentSlide + 1);
}, interval);
}, [interval, handleSlideChange, currentSlide]);
const destroyInterval = useCallback(() => {
clearInterval(timer.current);
}, []);
useEffect(() => {
if (autoPlay) {
createInterval();
return () => destroyInterval();
}
}, [autoPlay, createInterval, destroyInterval]);
return (
<React.Fragment>
<p style={{ fontSize: 20 }}>
{currentSlide} - {savedSlides?.length}
</p>
<CarouselContainer
onMouseEnter={() => {
if (autoPlay) {
destroyInterval();
}
}}
onMouseLeave={() => {
if (autoPlay) {
createInterval();
}
}}
>
<CarouselSlides currentSlide={currentSlide}>
{savedSlides}
</CarouselSlides>
{arrow ? (
<div>
<LeftButton onClick={() => handleSlideChange(currentSlide - 1)}>
❮
</LeftButton>
<RightButton onClick={() => handleSlideChange(currentSlide + 1)}>
❯
</RightButton>
</div>
) : null}
{dots ? (
<Dots>
{savedSlides.map((i, index) => (
<Dot
key={index}
onClick={() => handleSlideChange(index)}
active={currentSlide === index}
/>
))}
</Dots>
) : null}
</CarouselContainer>
</React.Fragment>
);
}
);
// This is my styled components
const Buttons = styled.a`
cursor: pointer;
position: relative;
font-size: 18px;
transition: 0.6s ease;
user-select: none;
height: 50px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: calc(50% - 25px);
position: absolute;
&:hover {
background-color: rgba(0, 0, 0, 0.8);
}
`;
const RightButton = styled(Buttons)`
border-radius: 3px 0 0 3px;
right: 0;
`;
const LeftButton = styled(Buttons)`
border-radius: 0px 3px 3px 0px;
left: 0;
`;
const Dots = styled.div`
display: flex;
justify-content: center;
align-items: center;
align-content: center;
margin-top: 10px;
`;
const Dot = styled.span<{ active: boolean }>`
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 10px;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
background-color: ${({ active }) => (active ? `red` : `#eeeeee`)};
`;
const CarouselContainer = styled.div`
overflow: hidden;
position: relative;
width: ${IMG_WIDTH}px;
height: ${IMG_HEIGHT}px;
img {
width: ${IMG_WIDTH - 20}px;
height: ${IMG_HEIGHT - 50}px;
margin-left: 10px;
margin-top: 15px;
}
z-index: 1;
`;
const CarouselSlide = styled.div`
flex: 0 0 auto;
transition: transform 500ms linear;
width: 100%;
transition: all 0.5s ease;
`;
const CarouselSlides = styled.div<{
currentSlide: ICarousel["currentSlide"];
}>`
display: flex;
${({ currentSlide }) =>
` transform: translateX(-${currentSlide ? currentSlide * 100 + `%` : 0})`};
transition: all 0.5s ease-in-out;
cursor: pointer;
`;
import*as React from“React”;
导入“/styles.css”;
从“/Carousel”导入旋转木马;
导出常量imgUrls=[
`https://images.unsplash.com/photo-1455849318743-b2233052fcff?ixlib=rb-1.2.1&ixid=eyjhcbfawqiojeymdd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyjhcbfawqiojeymdd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-1.2.1&ixid=eyjhcbfawqiojeymdd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1494253109108-2e30c049369b?ixlib=rb-1.2.1&ixid=eyjhcbfawqiojeymdd9&auto=format&fit=crop&w=900&q=60`
];
导出默认函数App(){
返回(
);
}
这是我的转盘组件
import * as React from "react";
import "./styles.css";
import Carousel from "./carousel";
export const imgUrls = [
`https://images.unsplash.com/photo-1455849318743-b2233052fcff?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1494253109108-2e30c049369b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`
];
export default function App() {
return (
<div className="App">
<Carousel slides={imgUrls} autoPlay dots />
</div>
);
}
import React, { useState, useEffect, useRef, memo, useCallback } from "react";
import styled from "styled-components";
export interface ICarousel {
children: JSX.Element[];
currentSlide?: number;
autoPlay?: boolean;
dots?: boolean;
interval?: number;
arrow?: boolean;
slideTest?: number;
}
const IMG_WIDTH = 320;
const IMG_HEIGHT = 700;
export default memo(
({
autoPlay = false,
dots = false,
interval = 2000,
arrow = false,
slideTest,
slides // This is my props which is coming from parent,
}: ICarousel) => {
const [savedSlides, setSavedSlides] = useState([]);
const [currentSlide, setSlide] = useState(0);
const [isPlaying, setIsPlaying] = useState(autoPlay);
const timer = useRef<any>(undefined);
useEffect(() => {
setSavedSlides(
slides?.map((slide, index) => {
return (
<CarouselSlide key={slide}>
<img
key={slide}
src={slide}
alt={`Example of mobile application ${index}`}
style={{
borderRadius: `20px`
}}
/>
</CarouselSlide>
);
})
);
}, [slides]);
// console.log(savedSlides);
// console.log(savedSlides.length);
const handleSlideChange = useCallback(
(index: number) => {
// IN here I made the condition but it does not work what I am expecting .
// I want the first will go all the way to last slide
setSlide(
index > savedSlides.length - 1
? 0
: index < 0
? savedSlides.length - 1
: index
);
},
[savedSlides]
);
const createInterval = useCallback(() => {
timer.current = setInterval(() => {
handleSlideChange(currentSlide + 1);
}, interval);
}, [interval, handleSlideChange, currentSlide]);
const destroyInterval = useCallback(() => {
clearInterval(timer.current);
}, []);
useEffect(() => {
if (autoPlay) {
createInterval();
return () => destroyInterval();
}
}, [autoPlay, createInterval, destroyInterval]);
return (
<React.Fragment>
<p style={{ fontSize: 20 }}>
{currentSlide} - {savedSlides?.length}
</p>
<CarouselContainer
onMouseEnter={() => {
if (autoPlay) {
destroyInterval();
}
}}
onMouseLeave={() => {
if (autoPlay) {
createInterval();
}
}}
>
<CarouselSlides currentSlide={currentSlide}>
{savedSlides}
</CarouselSlides>
{arrow ? (
<div>
<LeftButton onClick={() => handleSlideChange(currentSlide - 1)}>
❮
</LeftButton>
<RightButton onClick={() => handleSlideChange(currentSlide + 1)}>
❯
</RightButton>
</div>
) : null}
{dots ? (
<Dots>
{savedSlides.map((i, index) => (
<Dot
key={index}
onClick={() => handleSlideChange(index)}
active={currentSlide === index}
/>
))}
</Dots>
) : null}
</CarouselContainer>
</React.Fragment>
);
}
);
// This is my styled components
const Buttons = styled.a`
cursor: pointer;
position: relative;
font-size: 18px;
transition: 0.6s ease;
user-select: none;
height: 50px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: calc(50% - 25px);
position: absolute;
&:hover {
background-color: rgba(0, 0, 0, 0.8);
}
`;
const RightButton = styled(Buttons)`
border-radius: 3px 0 0 3px;
right: 0;
`;
const LeftButton = styled(Buttons)`
border-radius: 0px 3px 3px 0px;
left: 0;
`;
const Dots = styled.div`
display: flex;
justify-content: center;
align-items: center;
align-content: center;
margin-top: 10px;
`;
const Dot = styled.span<{ active: boolean }>`
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 10px;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
background-color: ${({ active }) => (active ? `red` : `#eeeeee`)};
`;
const CarouselContainer = styled.div`
overflow: hidden;
position: relative;
width: ${IMG_WIDTH}px;
height: ${IMG_HEIGHT}px;
img {
width: ${IMG_WIDTH - 20}px;
height: ${IMG_HEIGHT - 50}px;
margin-left: 10px;
margin-top: 15px;
}
z-index: 1;
`;
const CarouselSlide = styled.div`
flex: 0 0 auto;
transition: transform 500ms linear;
width: 100%;
transition: all 0.5s ease;
`;
const CarouselSlides = styled.div<{
currentSlide: ICarousel["currentSlide"];
}>`
display: flex;
${({ currentSlide }) =>
` transform: translateX(-${currentSlide ? currentSlide * 100 + `%` : 0})`};
transition: all 0.5s ease-in-out;
cursor: pointer;
`;
import React,{useState,useffect,useRef,memo,useCallback}来自“React”;
从“样式化组件”导入样式化;
导出接口ICarousel{
子元素:JSX.Element[];
当前幻灯片?:编号;
自动播放?:布尔;
点?:布尔;
间隔?:数字;
箭头?:布尔值;
幻灯片测试?:编号;
}
常数IMG_宽度=320;
常数IMG_高度=700;
导出默认备忘(
({
自动播放=错误,
点=假,
间隔=2000,
箭头=假,
幻灯片测试,
幻灯片//这是我的道具,来自家长,
}:ICarousel)=>{
const[savedSlides,setSavedSlides]=useState([]);
常数[currentSlide,setSlide]=使用状态(0);
const[isplay,setisplay]=使用状态(自动播放);
const timer=useRef(未定义);
useffect(()=>{
塞萨维兹利兹酒店(
幻灯片?.map((幻灯片,索引)=>{
返回(
);
})
);
},[幻灯片];
//console.log(savedSlides);
//console.log(savedSlides.length);
const handleSlideChange=useCallback(
(索引:编号)=>{
//在这里,我创造了条件,但它不工作,我期待的。
//我希望第一张幻灯片一直到最后一张幻灯片
固定滑块(
索引>savedSlides.length-1
? 0
:指数<0
?savedSlides.length-1
:索引
);
},
[savedSlides]
);
const createInterval=useCallback(()=>{
timer.current=setInterval(()=>{
无手柄滑座更换(当前滑座+1);
},间隔);
},[interval,handleSlideChange,currentSlide]);
const destroyInterval=useCallback(()=>{
清除间隔(定时器、电流);
}, []);
useffect(()=>{
如果(自动播放){
createInterval();
return()=>destroyInterval();
}
},[autoPlay,createInterval,destroyInterval]);
返回(
{currentSlide}-{savedSlides?.length}
{
如果(自动播放){
破坏间隔();
}
}}
onMouseLeave={()=>{
如果(自动播放){
createInterval();
}
}}
>
{savedSlides}
{阿罗(
handleSlideChange(当前幻灯片-1)}>
❮
handleSlideChange(当前幻灯片+1)}>
❯
):null}
{点(
{savedSlides.map((i,索引)=>(
handleSlideChange(索引)}
活动={currentSlide===index}
/>
))}
):null}
);
}
);
//这是我设计的组件
const Buttons=styled.a`
光标:指针;
位置:相对位置;
字号:18px;
过渡:0.6s缓解;
用户选择:无;
高度:50px;
宽度:40px;
显示器:flex;
证明内容:中心;
对齐项目:居中;
对齐内容:居中对齐;
顶部:calc(50%-25px);
位置:绝对位置;
&:悬停{
背景色:rgba(0,0,0,0.8);
}
`;
const RightButton=已设置样式(按钮)`
边界半径:3px 0 3px;
右:0;
`;
const LeftButton=已设置样式(按钮)`
边界半径:0px 3px 0px;
左:0;
`;
常量点=styled.div`
显示器:flex;
证明内容:中心;
对齐项目:居中;
对齐内容:居中对齐;
边缘顶部:10px;
`;
const Dot=styled.span`
光标:指针;
高度:15px;
宽度:15px;
利润率:0.10px;
边界半径:50%;
显示:内联块;
过渡:背景色0.6s;
背景色:${({active})=>(active?`red`:`eeeeeeee`});
`;
const CarouselContainer=styled.div`
溢出:隐藏;
位置:相对位置;
宽度:${IMG_width}px;
高度:${IMG_height}px;
img{
宽度:${IMG_width-20}px;
高度:${IMG_高度-50}px;
左边距:10px;
边缘顶部:15px;
}
z指数:1;
`;
const CarouselSlide=styled.div`
flex:0自动;
过渡:变换500ms线性;
宽度:100%;
过渡:所有0.5s缓解;
`;
const CarouselSlides=styled.div`
显示器:flex;
${({currentSlide})=>
`转换:translateX(${currentSlide?currentSlide*100+`%`:0});
过渡:所有0.5s缓进缓出;
光标:指针;
`;
您可能需要在此处使用大于等于(>=)更改大于
setSlide(
索引>savedSlides.length-1
? 0
:指数<0
?savedSlides.length-1
:索引
)