master
LiuJiaNan 2026-02-10 15:09:50 +08:00
parent c026a96bf0
commit ef3bd3509e
2 changed files with 28 additions and 20 deletions

View File

@ -1,5 +1,5 @@
import { motion } from "motion/react";
import { useContext, useState } from "react";
import { useContext } from "react";
import collapseMenuImg1 from "~/assets/images/map_bi/content/collapse_menu1.png";
import collapseMenuImg2 from "~/assets/images/map_bi/content/collapse_menu2.png";
import collapseMenuBg1 from "~/assets/images/map_bi/content/collapse_menu_bg1.png";
@ -31,8 +31,6 @@ import "./index.less";
function Content(props) {
const { currentPort, currentBranchOffice, pureMap, bottomUtilsCurrentIndex } = useContext(Context);
const [collapseLeft, setCollapseLeft] = useState(false);
const [collapseRight, setCollapseRight] = useState(false);
const {
controls: indexInfoControls,
@ -46,10 +44,10 @@ function Content(props) {
controls: leftControls,
displayedContent: leftDisplayedContent,
isVisible: isLeftVisible,
isCollapsed: isLeftCollapsed,
handleCollapse: handleLeftCollapse,
} = useContentAnimation({
currentContent: { currentPort, currentBranchOffice, bottomUtilsCurrentIndex },
isCollapsed: collapseLeft,
side: "left",
isPureMap: pureMap,
type: "panel",
@ -59,10 +57,10 @@ function Content(props) {
controls: rightControls,
displayedContent: rightDisplayedContent,
isVisible: isRightVisible,
isCollapsed: isRightCollapsed,
handleCollapse: handleRightCollapse,
} = useContentAnimation({
currentContent: { currentBranchOffice, bottomUtilsCurrentIndex },
isCollapsed: collapseRight,
side: "right",
isPureMap: pureMap,
type: "panel",
@ -162,9 +160,9 @@ function Content(props) {
if (currentPort === "00003" && !currentBranchOffice) {
return (
<div
className={`collapse_menu port left ${collapseLeft ? "active" : ""}`}
className={`collapse_menu port left ${isLeftCollapsed ? "active" : ""}`}
style={{ backgroundImage: `url(${collapseMenuBg1})` }}
onClick={() => handleLeftCollapse(setCollapseLeft)}
onClick={() => handleLeftCollapse()}
>
<img src={collapseMenuImg1} alt="" />
</div>
@ -178,18 +176,18 @@ function Content(props) {
<>
{bottomUtilsCurrentType !== "camera" && (
<div
className={`collapse_menu branch_office left ${collapseLeft ? "active" : ""}`}
className={`collapse_menu branch_office left ${isLeftCollapsed ? "active" : ""}`}
style={{ backgroundImage: `url(${collapseMenuBg2})` }}
onClick={() => handleLeftCollapse(setCollapseLeft)}
onClick={() => handleLeftCollapse()}
>
<img src={collapseMenuImg2} alt="" />
</div>
)}
{bottomUtilsCurrentIndex === -1 && (
<div
className={`collapse_menu branch_office right ${collapseRight ? "active" : ""}`}
className={`collapse_menu branch_office right ${isRightCollapsed ? "active" : ""}`}
style={{ backgroundImage: `url(${collapseMenuBg2})` }}
onClick={() => handleRightCollapse(setCollapseRight)}
onClick={() => handleRightCollapse()}
>
<img src={collapseMenuImg2} alt="" />
</div>

View File

@ -11,7 +11,6 @@ import { useEffect, useRef, useState } from "react";
*
* @param {object} params - 参数对象
* @param {object} params.currentContent - 当前要显示的内容状态包含 currentPortcurrentBranchOfficebottomUtilsCurrentIndex
* @param {boolean} params.isCollapsed - 当前是否处于折叠状态 panel 类型
* @param {string} params.side - 'left' 'right'控制动画方向 panel 类型
* @param {boolean} params.isPureMap - 是否为纯地图模式 panel 类型
* @param {string} params.type - 动画类型"index" "panel"默认 "panel"
@ -19,11 +18,11 @@ import { useEffect, useRef, useState } from "react";
* - controls: motion 动画控制器
* - displayedContent: 延迟显示的内容状态 panel 类型
* - isVisible: 元素可见性状态
* - isCollapsed: 折叠状态 panel 类型
* - handleCollapse: 处理折叠/展开的函数 panel 类型
*/
export function useContentAnimation({
currentContent,
isCollapsed = false,
side = "left",
isPureMap = false,
type = "panel",
@ -44,10 +43,18 @@ export function useContentAnimation({
// 标记是否是首次渲染(首次渲染不执行离开动画,直接进入)
const isFirstRender = useRef(true);
// 折叠状态(仅 panel 类型使用)
// true: 面板被折叠
// false: 面板展开
const [isCollapsed, setIsCollapsed] = useState(false);
// 延迟显示的内容状态(仅 panel 类型使用)
// 作用:在内容切换时,先显示旧内容,动画完成后再更新为新内容
const [displayedContent, setDisplayedContent] = useState(type === "index" ? {} : currentContent);
// 标记是否正在手动处理折叠/展开(防止 useEffect 干预)
const isManualCollapseAnimating = useRef(false);
// ==================== IndexInfo 类型的缩放动画逻辑 ====================
useEffect(() => {
@ -145,21 +152,20 @@ export function useContentAnimation({
// ==================== 折叠/展开处理 ====================
// 标记是否正在手动处理折叠/展开(防止 useEffect 干预)
const isManualCollapseAnimating = useRef(false);
/**
* 处理折叠按钮点击事件
* @param {Function} setCollapseState - setState 函数用于更新折叠状态
*/
const handleCollapse = (setCollapseState) => {
const handleCollapse = () => {
if (isCollapsed) {
// ==================== 展开逻辑 ====================
// 标记开始手动处理折叠/展开动画(阻止 useEffect 干预)
isManualCollapseAnimating.current = true;
// 1. 先同步显示内容(确保显示最新的内容)
setDisplayedContent(currentContent);
// 2. 更新折叠状态
setCollapseState(false);
setIsCollapsed(false);
// 3. 显示元素
setIsVisible(true);
@ -178,6 +184,9 @@ export function useContentAnimation({
x: 0, // 移动到正常位置
opacity: 1, // 淡入
transition: { duration: 0.5, ease: "easeOut" },
}).then(() => {
// 动画完成后清除手动处理标记
isManualCollapseAnimating.current = false;
});
});
});
@ -198,7 +207,7 @@ export function useContentAnimation({
setIsVisible(false);
// 2. 更新折叠状态为 true
setCollapseState(true);
setIsCollapsed(true);
// 3. 清除手动处理标记
isManualCollapseAnimating.current = false;
@ -357,6 +366,7 @@ export function useContentAnimation({
controls, // motion 动画控制器
displayedContent, // 延迟显示的内容(用于动画过渡)
isVisible, // 元素可见性状态
isCollapsed, // 折叠状态
handleCollapse, // 折叠/展开处理函数
};
}