reactjs 如何添加侧边栏关闭动画?

k4ymrczo  于 2023-08-04  发布在  React
关注(0)|答案(1)|浏览(63)

我在react和tailwindcss的帮助下创建了一个侧边栏菜单。
当用户点击汉堡包图标(菜单)时,边栏会从左到右出现,带有轻微的动画。我目前正在尝试做同样的动画后,用户离开侧边栏,在相反的方向(侧边栏消失,从右到左),但它老实说不适合我。我试过很多方法,但似乎代码本身的某些东西阻止了这样的动画工作。
你能看一下代码,试着向我解释一下实现这个效果的最佳方法以及我为自己设定的目标吗?
这是我的react菜单组件:

import React, { useRef, useState } from 'react';
import Sidebar from "./Sidebar";

const Menu = ({ sidebarOpen, toggleSidebar }) => {
    const containerRef = useRef(null);
    const sidebarRef = useRef(null);
    const [animationComplete, setAnimationComplete] = useState(false);

    const handleToggleSidebar = () => {
        if (!sidebarOpen) {
            setAnimationComplete(false);
        }
        toggleSidebar(!sidebarOpen);
    };

    React.useEffect(() => {
        if (sidebarOpen) {
            document.body.classList.add("sidebar-open");
            document.body.style.overflow = "hidden";
        } else {
            document.body.classList.remove("sidebar-open");
            document.body.style.overflow = "auto";
        }
    }, [sidebarOpen]);

    React.useEffect(() => {
        if (sidebarOpen && containerRef.current && !animationComplete) {
            const sidebarElement = sidebarRef.current;
            sidebarElement.style.transform = "translateX(-100%)";
            sidebarElement.style.transition = "transform 0s";
            requestAnimationFrame(() => {
                sidebarElement.style.transform = "translateX(0)";
                sidebarElement.style.transition = "transform 0.5s";
                setAnimationComplete(true);
            });
        }
    }, [sidebarOpen, animationComplete]);

    return (
        <div className="fixed bottom-0 left-0 w-full bg-white z-50 border-t-1 border-green-900">
            <div className="h-[60px] flex items-center justify-between">

                <div className="flex items-center ml-4">
                    <div
                        ref={containerRef}
                        className="cursor-pointer p-3"
                        onClick={handleToggleSidebar}
                    >
                        <div className={`h-1 w-6 bg-green-700 rounded mb-1 ${sidebarOpen ? 'opacity-0' : ''}`}></div>
                        <div className={`h-1 w-6 bg-green-700 rounded mb-1 ${sidebarOpen ? 'opacity-0' : ''}`}></div>
                        <div className={`h-1 w-6 bg-green-700 rounded ${sidebarOpen ? 'opacity-0' : ''}`}></div>
                    </div>
                </div>

            </div>
            {sidebarOpen && (
                <>
                    <div className="fixed top-0 left-0 right-0 bottom-0 z-0 bg-gray-700 opacity-50" onClick={() => toggleSidebar(false)}></div>
                    <div ref={sidebarRef} className="fixed top-0 left-0 bottom-0 z-10 w-full max-w-[20rem] p-4 bg-white shadow-xl shadow-blue-gray-900/5">
                        <Sidebar />
                    </div>
                </>
            )}
        </div>
    );
}

export default Menu;

字符串
这是自定义css侧边栏-打开:

body.sidebar-open {
  overflow: hidden;
}


这一点都不相关,但你也可以看看我的侧边栏组件(因为它在菜单组件中提到:

function scrollToTop() {
    window.scrollTo(0, 0);
}

const Sidebar = forwardRef((props, ref) => {
    const [open, setOpen] = React.useState(0);
    const [openAlert, setOpenAlert] = React.useState(true);

    const handleOpen = (value) => {
        setOpen(open === value ? 0 : value);
    };

    return (
        <Card ref={ref} className="fixed top-0 left-0 h-[calc(100vh-2rem)] w-full max-w-[20rem] p-4 shadow-xl shadow-blue-gray-900/5 overflow-y-auto">
         
            <List>
                <Accordion
                    open={open === 1}
                    icon={
                        <ChevronDownIcon
                            strokeWidth={2.5}
                            className={`mx-auto h-4 w-4 transition-transform ${open === 1 ? "rotate-180" : ""}`}
                        />
                    }
                >
                    <Link to="/home" onClick={scrollToTop}>
                        <ListItem className="focus:bg-green-50 hover:bg-green-50">
                                <ListItemPrefix>
                                    <HomeIcon className="h-5 w-5 text-green-900" />
                                </ListItemPrefix>
                                <Typography color="blue-gray" className="mr-auto font-normal">
                                    Home
                                </Typography>
                        </ListItem>
                    </Link>

                    <ListItem className="p-0 focus:bg-green-50 hover:bg-green-50" selected={open === 1}>
                        <AccordionHeader onClick={() => handleOpen(1)} className="border-b-0 p-3">
                            <ListItemPrefix>
                                <PresentationChartBarIcon className="h-5 w-5 text-green-900" />
                            </ListItemPrefix>
                            <Typography color="blue-gray" className="mr-auto font-normal">
                                Dashboard
                            </Typography>
                        </AccordionHeader>
                    </ListItem>

                    <AccordionBody className="py-1">
                        <List className="p-0">
                            <Link to="/balance" onClick={scrollToTop}>
                                <ListItem className="focus:bg-green-50 hover:bg-green-50">
                                    <ListItemPrefix>
                                        <ChevronRightIcon strokeWidth={3} className="h-3 w-5" />
                                    </ListItemPrefix>
                                    Balance
                                </ListItem>
                            </Link>

etc...


注意:为了简单起见,我删除了一些不相关的代码,这就是为什么我在代码中添加了一些额外的tailwindcss属性。

hs1rzwqc

hs1rzwqc1#

你的动画没有播放,因为你从HTML中删除了CSS类,当你添加CSS类时,它也添加了它的属性,所以动画可以播放,但在删除类时,它从DOM中删除了,所以它不能访问它的属性。

解决方案您可以在父侧边栏上添加一个必须切换的类,而不是直接操作DOM。${sidebaropen}?"classname to show sidebar":"classname to hide sidebar"记住CSS中有一些属性允许动画。

如果你仍然发现一些问题,请分享到Git repo或其他在线代码编辑器的链接,我们可以在那里解决这个问题。

相关问题