如何在用户第一次滚动时动态调整旋转木马的大小?

问题描述 投票:0回答:0

在细节之前,我想告诉你我正在使用带有 Tailwind CSS 的 Next js 并使用 Splide 库进行轮播。

问题:
我的 Next js 网站上有一个主旋转木马,当网站第一次加载时,旋转木马占据了屏幕的整个宽度和高度。当用户稍微滚动时,我想将此旋转木马的大小调整为 80% 的宽度和高度。如果仍然有困惑,请访问这个“Balmain”网站并滚动,你会明白我在说什么:
https://us.balmain.com/en

我尝试了什么:

所以我想实现这种类型的东西并且我在这方面非常成功。实际上,我创建了一个状态并在我的 useEffect 挂钩中监听了一个滚动事件,当滚动位置超过 0 像素时,我将状态更改为“true”,当它变为 true 时,三元运算符为旋转木马提供受尊重宽度的顺风 calsses和身高。
但这里的问题是,即使在放置了一个依赖数组(epmty)、带状态的依赖数组、删除了事件监听器之后,我的组件仍然在每个滚动事件上重新渲染,这使得它有太多的故障和缓慢。
所以没有其他方法可以做到这一点或者我做错了什么请澄清。

大家可以去看看我部署在vercel上的网站:

https://urbanfits-npvv45dd2-dark-reaper6.vercel.app

这是我的 index.js 代码;

import React, { useEffect, useState } from 'react'
import dynamic from "next/dynamic";
import Head from 'next/head'
import Navbar from '../components/navbar'
import Footer from '@/components/footer';
// import { Inter } from '@next/font/google'
import Carousel from '@/components/carousels/carousel';
import CardCarousel from '@/components/carousels/cardCarousel';
import Card from '@/components/cards/card';
import PicCard from '@/components/cards/picCard';

// Modal imports
import LoadingModal from '../components/modals/loadingmodal';
import LanguageModal from '../components/modals/languagemodal';

// imports for images
import Image from 'next/image';
import Logo from '../public/logos/logo_black.svg'
import image1 from '../public/card imgs/card img5.jpg'
import image2 from '../public/card imgs/card img6.jpg'
import image3 from '../public/card imgs/card img1.jpg'
import image4 from '../public/card imgs/card img8.jpg'

// Confifure font
// const inter = Inter({ subsets: ['latin'] })

function Home() {
    // state for navbar expansion
    const [expand, setExpand] = useState(false)
    // states and function for modals
    const [modal1, setModal1] = useState(false)
    const [modal3, setModal3] = useState(false)
    const toggleModal = (e) => {
        if (e.target.name === "modal1") {
            if (modal1 === false) return setModal1(true)
            if (modal1 === true) return setModal1(false)
        }
        else if (e.target.name === "modal3") {
            if (modal3 === false) return setModal3(true)
            if (modal3 === true) return setModal3(false)
        }
    }

    const [resize, setResize] = useState(false)

    useEffect(() => {
        const setSizefunc = () => {
            let position = window.pageYOffset
            if (position >> 0) {
                setResize(true)
                console.log(position)
            }
        }
        window.addEventListener('scroll', setSizefunc )
        window.removeEventListener('scroll', setSizefunc)
    },[])

    useEffect(() => {
        setModal1(true)
    }, [])

    return (
        <>
            <Head>
                <title>Urban Fits</title>
                <meta name="description" content="Generated by create next app" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
            </Head>
            <main className="w-full h-full section_container">
                <Navbar logoNull setExpand={setExpand} classes={resize === true ? "" : "-translate-x-56 opacity-0 pointer-events-none"} />
                <LoadingModal show={modal1} toggleModal={toggleModal} />
                <LanguageModal show={modal3} toggleModal={toggleModal} />
                <section className={`${expand === true ? 'w-full lg:w-[79.4%]' : 'w-full'} bg-gray-100 float-right flex justify-center lg:justify-end transition-all duration-700`}>
                    <Image alt="Urban images" src={Logo} className={`${resize === true ? "" : "translate-x-44"} fixed top-6 right-6 md:top-10 md:right-10 z-10 w-14 md:w-20 transition-all duration-700`} ></Image>
                    <div className={`${resize === true ? "w-full lg:w-[94.6%]" : "w-full"} flex flex-col justify-center items-center space-y-5 transition-all duration-700`}>
                        <Carousel classes={resize === true ? "w-11/12 h-[80vh] md:h-[90vh] rounded-[2rem] mt-7 mx-auto lg:m-10" : "w-full h-screen"} />
                        {/* Auto scroll Carousel  */}
                        <section className="relative w-full h-screen p-3 md:p-5 md:pr-0 flex flex-col md:flex-row items-center justify-center font_futuraLT">
                            <div className="w-full md:w-[35%] md:h-full p-5 flex flex-col justify-center items-start">
                                <h2 className="text-2xl md:text-5xl word-wrap leading-tight">Newest Gear to Work</h2>
                                <h4 className="font_futuraLTlite text-lg">Innovation and Comfort for Women</h4>
                            </div>
                            <div className="w-full md:w-[70%] h-full">
                                <CardCarousel />
                            </div>
                            <div className="absolute w-1/5 h-full top-0 right-0 bg-gradient-to-l from-white to-transparent pointer-events-none"></div>
                        </section>
                        {/* Shopping Card Section */}
                        <section className="w-full h-screen p-3 md:p-10 flex flex-col lg:flex-row justify-between font_futuraLT space-y-7 lg:space-y-0 snap-center">
                            <PicCard object_fit="object-top" img={image1} />
                            <PicCard img={image2} />
                        </section>
                        {/* Shopping Card Section */}
                        <section className="w-full font_futuraLT snap-center">
                            <h3 className="text-4xl ml-10">Urban Unicorn Sneakers</h3>
                            <div className="w-full h-screen p-3 md:p-10 flex flex-col md:flex-row justify-between space-y-7 lg:space-y-0">
                                <PicCard img={image4} />
                                <PicCard img={image3} />
                            </div>
                        </section>
                        {/* Auto scroll Carousel  */}
                        <section className="relative w-full h-screen p-3 md:p-5 md:pr-0 flex flex-col md:flex-row font_futuraLT snap-center">
                            <div className="w-full md:w-[35%] md:h-full p-5 flex flex-col justify-center items-start">
                                <h2 className="text-2xl md:text-5xl word-wrap leading-tight self-start">Newest Gear to Work</h2>
                                <h4 className="font_futuraLTlite text-lg">Innovation and Comfort for Men</h4>
                            </div>
                            <div className="w-full md:w-[70%] h-full">
                                <CardCarousel />
                            </div>
                            <div className="absolute w-1/5 h-full top-0 right-0 bg-gradient-to-l from-white to-transparent pointer-events-none"></div>
                        </section>
                        {/* Ending Link Cards section */}
                        <section className="w-full h-auto lg:h-[80vh] p-5 flex flex-col lg:flex-row justify-around items-center space-y-6 lg:space-y-0">
                            <Card href="/contact" title="Contact Us" value='If you have any query then please contact us.' valueCenter btnValue="Contact Us" classes='w-full md:w-[60vw] py-20 justify-center items-center h-full lg:w-[30%] md:h-3/4' />
                            <Card href="/customercare" title="Customer Care" value='Do you have any questions? We are here to help you. You can contact our customer care team by email or over the phone.' valueCenter btnValue="Get In Touch" classes='lg:scale-110 w-full md:w-[60vw] py-20 justify-center items-center h-full lg:w-[30%] md:h-3/4' />
                            <Card href="/faq" title="FAQ" value='Find all the answers to the frequently asked questions below.' valueCenter btnValue="See Our FAQs" classes='w-full md:w-[60vw] py-20 justify-center items-center h-full lg:w-[30%] md:h-3/4' />
                        </section>
                        <Footer />
                    </div>
                </section>
            </main>
        </>
    )
}

export default dynamic(() => Promise.resolve(Home), { ssr: false })

这是我的 Splide Carousel 组件代码;


import React, { useRef, useState, useMemo } from 'react'
import LinkBtn from '../link_btn';
import { Splide, SplideTrack, SplideSlide } from '@splidejs/react-splide';
// Default theme
import '@splidejs/react-splide/css';

import Image from 'next/image';
import image1 from '../../public/carousel imgs/carousel img1.jpg'
import image2 from '../../public/carousel imgs/carousel img2.jpg'
import image3 from '../../public/carousel imgs/carousel img3.png'
import image4 from '../../public/carousel imgs/carousel img4.jpg'

//Carousel Images component
const CarouselSlide = (props) => {
    return (
        <SplideSlide key={props.li_key} className={`${props.size} relative  p-10`}>
            <div className="absolute w-2/6 bottom-[7%] left-[4%] flex flex-col items-start text-white text-5xl">
                <h1 className="text-white text-4xl md:font-bold">Denim</h1>
                <p className="mt-1 mb-4 text-xl font_futuraLTlite">For Women</p>
                <LinkBtn href="/productlisting" my="my-0" bg="bg-white" text="text-black" classes="w-full md:w-3/4 text-xs md:text-base" >Shope Now</LinkBtn>
            </div>
            <Image className='w-full h-full transition-all duration-700' src={props.img} alt="Urban images" />
        </SplideSlide>
    )
}

export default function Carousel(props) {
    const [play, setPlay] = useState(true)
    const togglePlay = () => {
        if (play === true) return setPlay(false)
        if (play === false) return setPlay(true)
    }

    // splide ref and function to move the slide to prevent the weird effect when the screen is resized
    let splideRef = useRef(null)

    //Carousel Options
    const carousel_options = {
        type: 'loop',
        speed: 1500,
        gap: '0.5rem',
        cover: true,
        autoplay: true,
        waitForTransition: true,
        resetProgress: false,
        interval: 3500,
        drag: false,
        focus: 0,
        pauseOnHover: false,
        pauseOnFocus: false,
        pagination: false
    }
    return (
        <div className={` ${props.classes} font_futuraLT transition-all duration-1000 overflow-hidden snap-center`}>
            <Splide ref={splideRef} className={`w-full h-full relative transition-all duration-1000`} hasTrack={false}
                options={useMemo(()=>{
                    return carousel_options
                }, [carousel_options])}>
                <SplideTrack className='w-full h-screen' >
                    {[image1, image2, image3, image4].map((img, index) => {
                        return <CarouselSlide li_key={index} size={props.classes} img={img} />
                    })}
                </SplideTrack>

                {/* Carousel Title */}
                <div className="w-full text-center absolute top-[40%] left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center text-white space-y-5">
                    <h1 className="text-5xl md:text-8xl">Urban Fits</h1>
                    <h3 className="font_futuraLTlite text-3xl md:text-5xl">United Arab Emirates</h3>
                </div>

                {/* Buttons for next, prev slide and to pause the carousel */}
                <div className="splide__arrows absolute flex space-x-5 bottom-12 right-10">

                    <button className="splide__arrow--prev hover:bg-gray-500 flex justify-center items-center w-8 h-8 rounded-full bg-white rotate-180 transition-all duration-500" >
                        <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M15.4689 22.4366C15.9575 22.1485 16.1328 21.6349 15.8823 21.2215C15.8197 21.115 14.8551 20.1066 13.7464 18.9854L11.7295 16.9372L17.2979 16.9247C23.3798 16.9059 23.0729 16.9247 23.3548 16.5426C23.455 16.411 23.4863 16.2732 23.4863 15.9976C23.4863 15.722 23.455 15.5842 23.3548 15.4527C23.0729 15.0706 23.3798 15.0894 17.2979 15.0706L11.7295 15.0581L13.7464 13.0099C14.8551 11.8887 15.8197 10.8803 15.8823 10.7738C16.1141 10.3917 15.995 9.94699 15.5816 9.62755C15.2747 9.38953 14.924 9.38953 14.5857 9.62128C14.4542 9.71524 13.0574 11.0807 11.479 12.6591C9.14265 15.008 8.61024 15.5717 8.56014 15.7659C8.42234 16.2732 8.39102 16.2357 11.479 19.3361C13.0574 20.9146 14.4417 22.2738 14.5669 22.3615C14.8926 22.587 15.1682 22.612 15.4689 22.4366Z" fill="black" />
                        </svg>
                    </button>

                    <button onClick={togglePlay} className="splide__toggle hover:bg-gray-500 flex justify-center items-center w-8 h-8 rounded-full bg-white  transition-all duration-500" >
                        {play === false ? <i className="material-symbols-rounded fill">play_arrow</i>
                            : <svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <line x1="1.25" y1="12" x2="1.25" stroke="black" strokeWidth="1.5" />
                                <line x1="7.25" y1="12" x2="7.25" stroke="black" strokeWidth="1.5" />
                            </svg>}
                    </button>

                    <button className="splide__arrow--next hover:bg-gray-500 flex justify-center items-center w-8 h-8 rounded-full bg-white transition-all duration-500" >
                        <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M16.531 9.56336C16.0425 9.85149 15.8671 10.3651 16.1176 10.7785C16.1803 10.885 17.1449 11.8934 18.2535 13.0146L20.2704 15.0628L14.7021 15.0753C8.62009 15.0941 8.92701 15.0753 8.64515 15.4574C8.54493 15.589 8.51361 15.7268 8.51361 16.0024C8.51361 16.278 8.54493 16.4158 8.64515 16.5473C8.92701 16.9294 8.62009 16.9106 14.7021 16.9294L20.2704 16.9419L18.2535 18.9901C17.1449 20.1113 16.1803 21.1197 16.1176 21.2262C15.8859 21.6083 16.0049 22.053 16.4183 22.3725C16.7252 22.6105 17.076 22.6105 17.4142 22.3787C17.5457 22.2848 18.9425 20.9193 20.521 19.3409C22.8573 16.992 23.3897 16.4283 23.4398 16.2341C23.5776 15.7268 23.6089 15.7643 20.521 12.6639C18.9425 11.0854 17.5583 9.72622 17.433 9.63853C17.1073 9.41304 16.8317 9.38798 16.531 9.56336Z" fill="black" />
                        </svg>
                    </button>
                </div>
            </Splide>
        </div>
    )
}
reactjs next.js react-hooks carousel splidejs
© www.soinside.com 2019 - 2024. All rights reserved.