react中使用动画react-spring写一个折叠面板

1.安装react-spring

npm install react-spring@9.7.3
npm install react-use-measure@2.1.1

2.html部分

import React, { useState, useEffect } from "react";
import { useSpring, animated } from "react-spring";
import useMeasure from 'react-use-measure';
import ArrowIcon from '@/assets/arrow.png';
import keyUpgradesIcon from '@/assets/14.png';
import "./index.less";

const CollapsablePanel = ({ title, content, activeId, coll, onChange, currentClick, className,headClassName,arrowAnimial=true,englishHeader, arrow, showArrow=true, keyUpgrades }) => {
    const currentClickId = currentClick?.id;
    const [isCollapsed, setIsCollapsed] = useState(true);
    const [ref, bounds] = useMeasure();

    useEffect(() => {
        console.log(coll,'content====')
        if((activeId && activeId == coll.id)){
            setIsCollapsed(false);
        }else {
            setIsCollapsed(true);
        }
    },[activeId]);
    const togglePanel = () => {
        setIsCollapsed((prevState) => !prevState);
        if(onChange){
            onChange(coll);
        }
    };
    const panelContentAnimatedStyle = useSpring({
        height: isCollapsed ? 0 : bounds.height,
    });
    const toggleWrapperAnimatedStyle = useSpring({
        transform: isCollapsed ? "rotate(0deg)" : "rotate(180deg)",
    });
    const showBac = isCollapsed && currentClick?.parentKey == coll.key;

    return (
        <div className={`${className || 'pannel'} ${isCollapsed || title == '新手入门'?'':'active-panel'}`} >
            <div onClick={togglePanel} className={`heading ${headClassName} ${(currentClickId && currentClickId == coll.id) || showBac?'active-header':''}`}>
                {
                    englishHeader?(
                        <div className="en-header-con" >
                            <div className="collapse-header-text cn-text" >{title}</div>
                            <div className="en-text" >Getting started</div>
                        </div>
                    ): (
                        <span className="collapse-header-text" >
                            {title} 
                            {keyUpgrades && <img alt="" src={keyUpgradesIcon}  />}
                        </span>
                    )
                }
                {
                showArrow? arrowAnimial?(
                        <animated.div className='arrow' style={toggleWrapperAnimatedStyle}>
                            <img  alt="" src={ArrowIcon} />
                        </animated.div>
                    ):(
                        <div className={`arrow ${arrow}`} >
                            <img  alt="" src={ArrowIcon} />
                        </div>
                    ):null
                }
            </div>
            {
                content?(
                    <animated.div
                        style={panelContentAnimatedStyle}
                        className="content"
                    >
                        <div ref={ref} className="contentInner" >
                            {content}
                        </div>
                    </animated.div>
                ):null
            }
        </div>
    );
};

export default CollapsablePanel;

3.css部分

.pannel {
    width: 100%;
    text-align: left;
    padding: 4px;
    border-radius: 10px;
    border-bottom: 0px;
    box-sizing: border-box;
    margin-bottom: 4px;
}
.active-panel{
    background: rgba(0,0,0,0.04);
}

.heading {
    line-height: 15px;
    padding: 9.5px 14px 9.5px 10px;
    color: rgba(0,0,0,0.86);
    font-size: 12px;
    border-radius: 8px;
    align-items: center;
    user-select: none;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    font-weight: bold;
    .ant-collapse-arrow{
        font-size: 11px;
    }
    .collapse-header-text{
        white-space: normal;
        word-wrap: break-word;
        word-break: break-all;
        display: flex;
        align-items: center;
        >img{
            width: 26px;
            margin-left: 5px;
        }
    }
    .en-header-con{
        padding: 14px 0px;
        .cn-text{
            height: 14px;
            line-height: 14px;
        }
        .en-text{
            color: rgba(0,0,0,0.46);
            font-size: 10px;
            height: 12px;
            line-height: 12px;
            margin-top: 4px;
        }
    }
    .arrow{
        min-width: 16px;
        height: 16px;
        margin-left: 24px;
        display: flex;
        img{
            width: 16px;
            height: 16px;
        }
    }
    .to-right{
        transform: rotate(-90deg);
    }
}
.active-header{
    background: linear-gradient(90deg,rgba(0,0,0,0.08), rgba(0,0,0,0.00));
}

.content {
    font-size: 10px;
    border-top: none;
    color: #000000;
    overflow: hidden;
    .coll-item {
        padding: 0 16px;
    }
}


.coll-item-con{
    padding: 4px 0px;
    cursor: pointer;
}
.coll-item{
    box-sizing: border-box;
    line-height: 28px;
    font-size: 12px;
    color: rgba(0,0,0,0.86);
    border-radius: 7px;
}
.active-item-con{
    .coll-item{
        background: linear-gradient(90deg,rgba(0,0,0,0.08), rgba(0,0,0,0.00));
    }
}
.white-coll{
    background-color: #fff;
    margin-bottom: 10px;
    border-radius: 14px;
    padding: 21.5px 4px;
    .heading{
        padding: 0px 14px 0px 10px;
        background-color: #fff;
        color: rgba(0,0,0,0.86);
        font-weight: bold;
        font-size: 14px;
        line-height: 17px;
    }
    .content {
        padding: 0 16px;
    }
    .contentInner {
        padding-top: 20px;
        padding-bottom: 20px;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值