setInterval我有三個順序影像,它們使用within附加到 DOM中useEffect。最終產品看起來像一個互動式影像,它作業得很好,減去了在安裝每個影像時存在非常非常微妙的抖動的事實。我寫得很快,還沒有重構,所以請原諒冗長。
import styles from './HeroImageSection.module.css'
import Image from 'next/image'
import React, { useState, useEffect, useRef } from 'react';
import Link from 'next/link'
import slideOne from './../../../public/assets/hero_images/1_nonumber.png'
import slideTwo from './../../../public/assets/hero_images/2_nonumber.png'
import slideThree from './../../../public/assets/hero_images/3_nonumber.png'
import Logo65Font from '../../global/ui/Logo65Font.js'
export default function HeroImageSection() {
const [isShowing, setIsShowing] = useState({
slideOne: true,
slideTwo: '',
slideThree: ''
})
useEffect(() =>{
let timer = setInterval(() => {
if (isShowing['slideOne'] === true){
setIsShowing(prevState => ({...prevState, ['slideOne']: false}))
setIsShowing(prevState => ({...prevState, ['slideTwo']: true}))
setIsShowing(prevState => ({...prevState, ['slideThree']: false}))
} else if (isShowing['slideThree'] === true && isShowing['slideOne'] === false){
setIsShowing(prevState => ({...prevState, ['slideOne']: true}))
setIsShowing(prevState => ({...prevState, ['slideTwo']: false}))
setIsShowing(prevState => ({...prevState, ['slideThree']: false}))
} else if (isShowing['slideOne'] === true && isShowing['slideTwo'] === false){
setIsShowing(prevState => ({...prevState, ['slideOne']: false}))
setIsShowing(prevState => ({...prevState, ['slideTwo']: true}))
setIsShowing(prevState => ({...prevState, ['slideThree']: false}))
} else if (isShowing['slideTwo'] === true && isShowing['slideThree'] === false){
setIsShowing(prevState => ({...prevState, ['slideOne']: false}))
setIsShowing(prevState => ({...prevState, ['slideTwo']: false}))
setIsShowing(prevState => ({...prevState, ['slideThree']: true}))
}
}, 1000)
return () => clearInterval(timer);
}, [isShowing])
return(
<section id={styles.heroImageSectionContainer}>
<div id={styles.centerImageTextContainer}>
<div id={styles.mobileLogo}>
<Logo65Font />
</div>
<div id={styles.heroTextContainer}>
<h1>Untouched pallets ready to be delivered to your driveway<span id={styles.periodColor}>.</span></h1>
<p><Link href={`/register`}><span id={styles.signUpUnderline}>Sign up</span></Link> to see shipping rates as you shop</p>
</div>
<div id={styles.heroImageContainer}>
<div className={isShowing['slideOne'] === true ? styles.centerImage : styles.displayNone}>
<Image alt="The flow of goods from retailer origin to your house." src={slideOne} priority={true} />
</div>
<div className={isShowing['slideTwo'] === true ? styles.centerImage : styles.displayNone}>
<Image alt="The flow of goods from retailer origin to your house." src={slideTwo} priority={true} />
</div>
<div className={isShowing['slideThree'] === true ? styles.centerImage : styles.displayNone}>
<Image alt="The flow of goods from retailer origin to your house." src={slideThree} priority={true} />
</div>
</div>
</div>
</section>
)
}
我使用每個影像的布林值來跟蹤它們是否應該根據其他兩個的狀態顯示。根據真實性,我要么使用具有的類,display: none要么添加必要的樣式類。顯然,抖動是因為洗掉了類,但我不確定如何才能平滑它,如果有的話?
假設我們以“反應方式”來做,并避免像這樣操作類:
{isShowing['slideOne'] === true ?
<div className={styles.centerImage}>
<Image alt="The flow of goods from retailer origin to your house." src={slideOne} priority={true} />
</div>
: ''}
{isShowing['slideTwo'] === true ?
<div className={styles.centerImage}>
<Image alt="The flow of goods from retailer origin to your house." src={slideTwo} priority={true} />
</div>
: ''}
{isShowing['slideThree'] === true ?
<div className={styles.centerImage}>
<Image alt="The flow of goods from retailer origin to your house." src={slideThree} priority={true} />
</div>
: ''}
最終結果是相同的,除了第一次運行過渡會導致閃爍,因此它實際上為行程添加了另一個錯誤。
我正在使用 flexbox 布局,這是centerImage類的樣子:
#centerImage{
display: flex;
width: 70%;
height: 100%;
justify-content: center;
}
希望大家給點建議!
編輯:影像的大小也完全相同。
uj5u.com熱心網友回復:
您使用條件渲染來隱藏/顯示影像。當影像第一次加載時,它會導致抖動。
同時掛載所有影像,并使用一個類來隱藏/顯示它們,并使用一個過渡來平滑變化。
const { useState, useEffect } = React;
const images = [
'https://picsum.photos/id/236/400/600',
'https://picsum.photos/id/237/400/600',
'https://picsum.photos/id/238/400/600'
];
function HeroImageSection() {
const [currentImage, setCurrentImage] = useState(0)
useEffect(() =>{
const timer = setInterval(() => {
setCurrentImage(prev => (prev 1) % images.length);
}, 1000);
return () => clearInterval(timer);
}, [])
return(
<div>
{images.map((url, idx) =>
<img key={url} src={url} className={`image ${idx === currentImage ? 'show-image' : ''}`} />
)}
</div>
)
}
ReactDOM
.createRoot(root)
.render(<HeroImageSection />);
.container {
position: relative;
height: 600px;
width: 400px;
}
.image {
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: opacity 0.5s;
}
.show-image {
opacity: 1;
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>
注意:如果您有大影像,加載可能仍需要更多時間。嘗試壓縮影像,并考慮僅在加載所有影像后才開始影片(請參見此處的示例)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/522739.html
