diff --git a/src/pages/Container/Map/components/Content/index.js b/src/pages/Container/Map/components/Content/index.js index c080ae6..283bea1 100644 --- a/src/pages/Container/Map/components/Content/index.js +++ b/src/pages/Container/Map/components/Content/index.js @@ -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 (
handleLeftCollapse(setCollapseLeft)} + onClick={() => handleLeftCollapse()} >
@@ -178,18 +176,18 @@ function Content(props) { <> {bottomUtilsCurrentType !== "camera" && (
handleLeftCollapse(setCollapseLeft)} + onClick={() => handleLeftCollapse()} >
)} {bottomUtilsCurrentIndex === -1 && (
handleRightCollapse(setCollapseRight)} + onClick={() => handleRightCollapse()} >
diff --git a/src/pages/Container/Map/components/Content/useContentAnimation.js b/src/pages/Container/Map/components/Content/useContentAnimation.js index 58ea3c7..2ab9d4e 100644 --- a/src/pages/Container/Map/components/Content/useContentAnimation.js +++ b/src/pages/Container/Map/components/Content/useContentAnimation.js @@ -11,7 +11,6 @@ import { useEffect, useRef, useState } from "react"; * * @param {object} params - 参数对象 * @param {object} params.currentContent - 当前要显示的内容状态(包含 currentPort、currentBranchOffice、bottomUtilsCurrentIndex 等) - * @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, // 折叠/展开处理函数 }; }